Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

CPTextView class missing #1432

Open
daboe01 opened this Issue · 56 comments

10 participants

@daboe01

Hi,
Will this be fixed?
Would you accept a port of the respective cocotron obj-c classes (MIT-license)?
Best greetings,
Daniel

@klaaspieter

I'm not a licensing expert, but I think we have other cocoatron inspired code in the framework so it should be fine. Be aware that this, even with example code, is a very complex task.

That said, I do encourage you to work on it if you have the time. I believe that if someone started work on it, the community will quickly help out to fill in the gap.

@aparajita
Owner

The relevant portion of the Cocotron license:

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

So licensing is not an issue. Actually implementing NSTextView in a browser is no joke. To fully implement it would mean doing your own text drawing and not rely on the underlying or elements.

Post something on the mailing list, a few people have already done some work on this. Better to benefit from their work or join forces than to start from scratch.

@Me1000

The goal was to build it on top of CoreText (which no longer seems like a priority for @nciagra). It would be nice if you could start by finishing the CoreText branch of Cappuccino, and building on top of that. :)

@aparajita
Owner

Contact Nicolas Goy kuon@goyman.com, he has been working on CoreText/CPTextView.

@daboe01

the core text project is currently idle on the side of nicolas goy

@kuon

Just to share some notes I made:

  • To be complete and a HUGE asset to cappuccino, CoreText must implement the following:
    1. Inline element support (images, non square elements (defined by bezier curves?)
    2. Right to left writings (also vertical right to left, like japanese)
    3. Kerning
    4. Intelligent selection (select word, line, paragraph with multiple click and keyboard shortcuts) and cursor navigation.
    5. Way of customizing the layout (like an app wants a ruler with tabs, we don't need to implement it, but we must architect our view to be customizable to that extent)
  • We must either use a canvas or use 1 div per character (google docs do so). Canvas would be prefered but I'm not sure all cappuccino supported browser supports it. But when the layout engine is done, then it's just a matter of implementing something like DrawCharacterAtPoint.
  • Getting font metrics is very limited with browsers, canvas has measureText which returns only a length, and using a div to measure text does not count for last character advance (for example an l is 1 pixel wide, but it's advance is more than that, so if you measure the word weasel you will get the actual bounding box in pixel) (this might be browser dependent also). There is also http://badassjs.com/post/16355968400/font-js-a-powerful-font-toolkit-for-javascript which might help. I have not digged very far, but I think our best bet would be to use our own font format, like we do for plist. This would require writing a tool that convert ttf fonts to something else. I might be way of topic here, I'm not sure. Again I noticed some problems with the inability to get detailed metrics for a font (I wrote a renderer for a game using freetype once, I use that as an "experience reference", but maybe there are some other ways, like using the dom to measure text, or maybe proper text measurement is not fully needed.).
  • Properly handling selection is not an easy task (for example with inline images, or right to left text), by not easy I don't mean hard to code, I mean hard to get the "right" behavior. I guess copying cocoa is the best way to go.

I cannot work on the project right now, but I'd be delighted to discuss about it.

@aljungberg
Owner

It's a hard problem but not as hard as all that. A TextView based on the CoreText branch was demonstrated at last year's CappCon. It included selection, keyboard navigation and all the other things you might expect.

Cappuccino is pretty good with measuring font metrics even within the limitations of the browser. See CPPlatformString metricsOfFont: and CPString sizeWithFont:.

I don't expect we'll ever do anything using one div per character. That's been tried before in Cappuccino apps and the performance is awful. Probably we will use canvas when available, and when not and we need to degrade I'd imagine one span per CTRun, not one per character.

I doubt we will see the TextView from CappCon materialise. Still, its existence shows that with the current CoreText branch, it's very doable as soon as someone volunteers time or money.

@kuon
@klaaspieter
@daboe01

i indeed found some stuff at github (emaillard/cappuccino) that follows the canvas approach.
i ported it to the current version of cappuccino. basic functionality is actually there after a bit of tweaking and debugging. i put a demo on http://aug-fancy.ukl.uni-freiburg.de/NewApplication/.
However, the code still needs tons of debugging/profiling and i have currently no idea how to get native copy/paste working without native text elements.

@kuon
@Me1000

Without looking at your code, I'd like to make sure you're using Cappuccino's built in copy/paste method calls... I believe they're part of CPResponder.

In order to use the native clipboard we need to add an invisible textfield to the page, set the value of the field to the string being copied, then select the text when onCopy or onBeforeCopy is called... Whatever it is. But, I thought Cappuccino already did that...

@daboe01

thank you for the hint. however, from the online documentation, only CPTextField implement copy/paste. Furthermore, these methods do nothing when called in browser environment.

@daboe01

please see https://github.com/daboe01/CPTextView for the stuff that i have so far

@aparajita
Owner

The text drawing in canvas looks terrible, and the performance is currently unusable based on the examples I have seen.

This is definitely something that needs addressing. If only we had access to the google docs engine or something like that.

@cappbot
Collaborator

Milestone: Someday. Labels: #accepted, #needs-patch, AppKit. What's next? This issue needs a volunteer to write and submit code to address it.

@daboe01

hi gents,
i just updated my CPTextView repo to use spans instead of canvas drawing. this seems the way to go.
new demo: http://aug-fancy.ukl.uni-freiburg.de/CPTextView
old demo: http://aug-fancy.ukl.uni-freiburg.de/NewApplication2

@aparajita
Owner

Definitely better than canvas. Still has some issues as I’m sure you know. Seems you are defining a TCL-like language using Cappuccino, no?

@aljungberg
Owner

Looks nice. Why do the spans have <br> in them?

@daboe01

the br' s obviously come from including the actual newline-character into the span. i will fix this, thanks.

@daboe01

hi aparajita, i am aware of the issues. a lot are already fixed in the repo. i cannot update the demo from home. the demo is actually a demo for https://github.com/daboe01/cappusance :-)

@daboe01

i just put a new demo online that has a bunch of issues fixed and also demonstrates some basic rich-editing capabilities.
http://aug-fancy.ukl.uni-freiburg.de/CPTextView

@aparajita
Owner
@aljungberg
Owner

Great progress!

I cut out some text and pasted it back in and it appeared in a different place than where I cut it.

@daboe01

thanks for the feedback! i just fixed your issues in my repo on https://github.com/daboe01/CPTextView. however, the fontpanel looks awful and needs to be redone.

@daboe01

i also fixed keyboard navigation issues and added color support (including drag-accepting from color-panel).
all in all, i do not see serious issues anymore.
the performance seems quite ok (at least for one-page documents) without looking into optimisation at all.
what do you think?
best greetings,
daniel

ps:
i can update the demo-app only early in next week. you can download the demo from my github if you do not want to wait.

@daboe01

i updated the demo app. remember to clear the browser-cache.

@timeimp

Wow.

daboe01, this is some seriously amazing work!

Can't wait for this to make it to master.

I'm curious - how does the font panel know which fonts to show? I ask as I have installed 9 800 fonts recently and loading font menus takes... a while, so I wonder if there would be any performance issues there.

  • timeimp
@aljungberg
Owner

Huge progress, selection works better, font panel works for me now, cut and paste on the same spot does what's expected. Here's another small bug: I selected the final e of the red title and the first character of the next line and did a "cut" - this caused the formatting of the title to be lost.

@daboe01

hi aljungberg
i have seen this also. it is actually a bug in CPAttributedString. the fix is non-trivial :-(

@daboe01

hi timeimp,
the fontpanel uses [[CPFontManager sharedFontManager] availableFonts] for the list.

@daboe01

yet another update! critical patches to CPAttributedString, copy/paste, undo, more bugs fixed.

@daboe01

NEW: CPParagraphStyle + Font panel now observes the selection + several bug fixes.
clear browser cache before loading the demo.

@daboe01

i did not get any feedback on bugs or missing features so far.
do you guys think, my stuff is mature enough to warrant a pull request?

@kerusan

I have a very small one and that is when alt selecting words with the keyboard arrow keys ( <- and -> ) the word gets correctly selected but also an extra space. This differs from Cocoa.

@aljungberg
Owner

When you make a selection and then press the right arrow key (without holding shift or anything) this should happen:

  • The selection gets cleared (✓ Works)
  • The cursor is moved to the right of where the selection was (Does not work)

Currently the cursor seems to be moved to the left side of the previous selection (probably the range .location).

You can copy and paste working code from CPTokenView - it already handles a lot of these selection situations. You'll find code for moveRightAndModifySelection: etc too. If you use all of these standard methods you get key bindings support.

https://github.com/cappuccino/cappuccino/blob/master/AppKit/CPTokenField.j#L828

- (void)moveRight:(id)sender
{
    // Right arrow
    if ((_selectedRange.location < [[self _tokens] count] || _selectedRange.length) && [self _editorValue] == "")
    {
        if (_selectedRange.length)
        {
            // Place the cursor at the end of the selection and collapse.
            _selectedRange.location = CPMaxRange(_selectedRange);
            _selectedRange.length = 0;
        }
        else
        {
            // Move the cursor forward one token if the input is empty and the right arrow key is pressed.
            _selectedRange.location = MIN([[self _tokens] count], _selectedRange.location + _selectedRange.length + 1);
        }

        [self setNeedsLayout];
        _shouldScrollTo = CPScrollDestinationRight;
    }
    else
    {
        // Allow cursor movement within the text field.
        [[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
    }
}
@Timovzl

Great work so far. If you're ready for some feedback, here are some details about keyboard control that aren't quite right yet.

N.B. For shift-based text selection, to get correct behavior, keep in mind that we are just moving the caret from its current position to a new position, and adding anything unselected in its wake to the selection, while removing anything already selected in its wake from the selection. Also, the caret is always in the position where the selection was finished. So if I select the word 'finished' from back to front, the caret is before the letter f.

Anyways, I have quite a list here. I'll be happy to test on Win and Mac when you have new upgrades.

  1. Shift+arrow to select.
    1. (Shift+arrow works when initially selecting.)
    2. Shift+left/right 'backwards' on an existing selection. Select some text, e.g. using shift+right. Then try to narrow your selection using shift+left. The rightmost selected character should fall off. (Because the caret is on the right end and being moved to the left. Try it in any text field.) Instead, more characters get selected to the left of the selection.
    3. Shift+up/down has the same issue of not being able to narrow the selection (but vertically).
    4. Shift+up/down, when there is no line above/below to select, should move the caret as far as is possible, i.e. shift+up on line zero should move the caret to position 0, and shift+down on the last line should move the caret to the end of the text.
    5. The above issues apply to shift+alt+arrow as well.
  2. Ctrl+shift+arrow seems to behave erratically. I haven't been able to quite pin down what's going on.
  3. Arrow keys while there is a selection. Currently the caret is moved, clearing the selection. If the caret cannot be moved, the selection is not cleared. The correct behavior is as follows: For left/right keys, place the caret at the start respectively the end of the selection. Always clear the selection. For up/down keys, do the exact same as left/right keys, and then move the caret up respectively down one line, if possible.
  4. Move to start/end. (I have not tested all of this.)
    1. Move to the start/end of the line. On Windows, this is home/end. On Mac, this is cmd+left/right.
    2. Move to the start/end of the text. On Windows, this is ctrl+home/end. On Mac, this cmd+up/down.
    3. The above also have very specific behaviors when coming from a selection. Compare to any HTML multiline text field for details.
  5. Other Mac/Windows differences.
    1. Ctrl+arrow on Windows should be similar to alt+arrow on Mac. (Not tested.)
    2. What does alt+arrow do on Windows? From the top of my head, I believe it does nothing. (Not tested.)
    3. ...
  6. What are the Linux standards?
  7. The tab key is generally expected to move the focus to the next input element. Currently, it places a tab character. I'm not sure if there generally is a way to place a tab character in text fields.
@daboe01

hi gents,
thank you very much for your valuable feedback. @kerusan : should be fixed now. @aljungberg : should be fixed now. @Timovzl : proper shift+arrow support required hefty refacturing, but it was worth it. thanks for pointing this out.

IMHO we should not mimic the platform (as we do not mimic the native controls). maybe this should be voted on the usenet. Anyway, this cannot be done in CPTextView because the actual modifier keys are abstracted away in CPKeyBinding.j.

@daboe01

any more issues?

@kerusan

Yes it seems like
when alt key and arrow key is pressed you save a (alt) start position. This position does not get cleared right.
Use case:
1. Place the cursor in the middle of a word.
2. Press alt & arrow keys to go to the next word
3. Release the alt key. Now we are standing at the end of the word.
4. Press Shift-alt arrow. Now the selection starts in the middle of the word where we started, not from the position at the end of the word where it should.

This error complies to all the arrow keys up, down, right and left.

Keep up the good work, this is fantastic.

@daboe01

fixed, thanks!

@daboe01

hi gang,
good news: i reached my personal milestone! all critical issues fixed that i was aware of.
would you prefer a PR with all classes in the main AppKit directory? Or do you guys fancy a CPTextView subdirectory inside?

@aljungberg
Owner

How many classes are there? If you already have a branch it'd be fine to just make a pull request out of it - it's good to have the full commit history, which can be very helpful when tracking down issues (as opposed to 1 enormous rebased commit).

@daboe01

IMHO no way to keep the full commit history.
At the moment, it is a standalone framework with 13 files (10 are new).
Three of the 13 are CPText.j, CPAttributedString.j and CPFontManagerAdditions.j. These comprise of monkey-patches for Cappuccino issues.
there already is PR #2045 for CPAttributedString.j
would you recommend separate PRs for CPFontManager and CPText?
or should i put it all in one PR?

@aljungberg
Owner

I'd recommend separate PRs.

@daboe01

thank you for the recommendation.
however, it turns out more complicated.
i have to move a lot of constants around to get rid of all circular inclusions.
the only option to get it all right, is to pull it all at once (save the stuff from PR #2045).
you can see my current layout at
https://github.com/daboe01/cappuccino/compare/NEW--CPTextView?expand=1

@daboe01

i made a final update to the online demo. you can see the latest speed optimisations for chrome.

@daboe01

i just updated the online demo from http://ansb.uniklinik-freiburg.de/CPTextView/ to reflect my recent fixes and optimisations to the typesetter and the layoutmanager. please let me know if you see issues.

@daboe01

i updated selection drawing to use DOM spans instead of canvas. This should be faster, look nicer and last but not least work with large text. We previously were hit by a size limitation of a canvas element. I updated the online demo so you guys can test this. please let me know if you see issues (remember to clear the browser cache).

@daboe01

i updated the online demo once more so you guys can verify that native pasting is now supported in safari. make sure to clear the browser cache.

@daboe01

updated the online demo so you guys can see the new regex based granularity engine. make sure to clear the browser cache

@aparajita
Owner

Absolutely awesome! Two issues I see:

  • When the Font panel is opened, the color is not set to the color of the text if all of the selected text is the same color.

  • When clicking on a letter, it always places the caret to the left of the letter. The caret should be placed to the right of the letter if the click point is >50% width of the letter.

@daboe01

thank you @aparajita.
i fixed both issues and updated the demo.
best greetings,
daniel

@aparajita
Owner

How are you calculating the character width? It seems the calculation is biased towards the left by a certain percentage, because at smaller font sizes I have to click farther to the right to get the caret to appear to the right.

@daboe01

i do not see it (testing in chrome)
the code is

 partialFraction[0] = (point.x - frames[j].origin.x) / frames[j].size.width;

it has to be a rounding issue.

@aparajita
Owner

I checked again zooming in on the screen, and it is working correctly. Great job!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.