Administrator
|
For VimPharo, I want to have a different cursor depending on whether a tool is in insert or normal mode.
I tried a handful of ways, but they all failed or worked partially/inconsistently. Here's some of them: * add the state to the paragraph, but the entire paragraph gets replaced during the life of the tool, so the state gets lost * add the state to the editor, but the situation is the same * add the state to PluggableTextMorph, override and access it from TextMorphForEditView>>updateFromParagraph. This was an extreme PITA and got me very acquainted with the emergency evaluator. It "worked", but only after using the arrows a bit. Does anyone have any idea where I might hook in? <rant>I find the whole text system very confusing. What the heck does a paragraph know about insertion points?? A view has one paragraph object, even if there are several paragraphs (as understood by the rest of humanity as a block of text with breaks between the adjoining ones. Editors and Paragraphs are thrown out and replaced on a whim. I'm finding it very hard to understand and modify</rant> Thanks, Sean
Cheers,
Sean |
On Jul 16, 2012, at 9:38 PM, Sean P. DeNigris wrote: > > <rant>I find the whole text system very confusing. :-) It's a mess of epic proportion. If you know take into account that the orignal plan of Squeak was to be the Medium to re-invent all Media... Marcus -- Marcus Denker -- http://marcusdenker.de |
In reply to this post by Sean P. DeNigris
I am also spending a hell of a lot of time on Text, Paragraph, Styler and other things like that (TextAttribute and subclasses).
Very complicated indeed. It was worse before I have been told. Phil
2012/7/16 Sean P. DeNigris <[hidden email]> For VimPharo, I want to have a different cursor depending on whether a tool |
Indeed it was :)
Alain Plantec did a great job about that :) Ben
On Jul 16, 2012, at 10:27 PM, [hidden email] wrote: I am also spending a hell of a lot of time on Text, Paragraph, Styler and other things like that (TextAttribute and subclasses). |
In reply to this post by Sean P. DeNigris
On Jul 16, 2012, at 9:38 PM, Sean P. DeNigris wrote: > For VimPharo, I want to have a different cursor depending on whether a tool > is in insert or normal mode. > > I tried a handful of ways, but they all failed or worked > partially/inconsistently. Here's some of them: > * add the state to the paragraph, but the entire paragraph gets replaced > during the life of the tool, so the state gets lost > * add the state to the editor, but the situation is the same > * add the state to PluggableTextMorph, override and access it from > TextMorphForEditView>>updateFromParagraph. This was an extreme PITA and got > me very acquainted with the emergency evaluator. It "worked", but only after > using the arrows a bit. > > Does anyone have any idea where I might hook in? > > <rant>I find the whole text system very confusing. What the heck does a > paragraph know about insertion points?? A view has one paragraph object, > even if there are several paragraphs (as understood by the rest of humanity > as a block of text with breaks between the adjoining ones. Editors and > Paragraphs are thrown out and replaced on a whim. I'm finding it very hard > to understand and modify</rant> I got burned by that when I worked on my botanics env…. it was terrible. > > Thanks, > Sean > > -- > View this message in context: http://forum.world.st/Customizing-the-Caret-of-a-PluggableTextMorph-tp4640245.html > Sent from the Pharo Smalltalk mailing list archive at Nabble.com. > |
In reply to this post by Sean P. DeNigris
Hi Sean, you can take a look at Athens-PangoCairo (in squeaksource).
Using NativeBoost, i'm using the Pango layout library [1], and the Pango-Cairo binding [2], to avoid laying out text using the outdated (and messy) stuff in the image. Check out the classes: ParagraphDescription & AthensPangoCairoParagraph. I'm using them as the basis for the TextShape,LabelShape, and EditableTextShape in Shapes / Gaucho ( using TextEditor, SingleLineEditor ). Maybe somebody can do the same for Morphic? use Pango to layout the text, and code a new TextMorph on top of it? Fernando [1] http://developer.gnome.org/pango/stable/pango-Layout-Objects.html [2] http://developer.gnome.org/pango/stable/pango-Cairo-Rendering.html On Wed, Jul 18, 2012 at 7:28 AM, Stéphane Ducasse <[hidden email]> wrote: > > On Jul 16, 2012, at 9:38 PM, Sean P. DeNigris wrote: > >> For VimPharo, I want to have a different cursor depending on whether a tool >> is in insert or normal mode. >> >> I tried a handful of ways, but they all failed or worked >> partially/inconsistently. Here's some of them: >> * add the state to the paragraph, but the entire paragraph gets replaced >> during the life of the tool, so the state gets lost >> * add the state to the editor, but the situation is the same >> * add the state to PluggableTextMorph, override and access it from >> TextMorphForEditView>>updateFromParagraph. This was an extreme PITA and got >> me very acquainted with the emergency evaluator. It "worked", but only after >> using the arrows a bit. >> >> Does anyone have any idea where I might hook in? >> >> <rant>I find the whole text system very confusing. What the heck does a >> paragraph know about insertion points?? A view has one paragraph object, >> even if there are several paragraphs (as understood by the rest of humanity >> as a block of text with breaks between the adjoining ones. Editors and >> Paragraphs are thrown out and replaced on a whim. I'm finding it very hard >> to understand and modify</rant> > > I got burned by that when I worked on my botanics env…. > it was terrible. > >> >> Thanks, >> Sean >> >> -- >> View this message in context: http://forum.world.st/Customizing-the-Caret-of-a-PluggableTextMorph-tp4640245.html >> Sent from the Pharo Smalltalk mailing list archive at Nabble.com. >> > > |
In reply to this post by Stéphane Ducasse
Ah, the morass into which I am currently digging...
Well, if we look at it for a while, it becomes a tad clearer. PluggableTextMorph is just a shell for a TextMorph. The TextMorph basically displays a Text (which can be styled with TextAttributes) When moving into edition, there is an editor known by the TextMorph but this is not an editor like I understood it, but rather a helper object that will come handy with TextMorph>>handleInteraction: interactionBlock
Inside handleInteraction, there is that editor and paragraph and then a call to interaction blockValue. And the interactionBlock is containing a bunch of various things that delegate the real editing work to the editor.
Like in aTextMorph>>handleInteraction: [editor mouseUp: evt] If you then look into the editor (mostly SmalltalkEditor right now in the image), you see a quite large method for that mouseUp: evt handling. And lots of other things.
There should be a cleanup occuring in the Editor -> TextEditor -> SmalltalkEditor hierarchy. The TextEditor knows a bit too much and I am currently implementing a child of TextEditor to have a simple, clean editor that does only the basics for my purpose. Once I am please with it, it may become an interesting child of Editor (maybe the TextEditor itself, with TextEditor renamed to something else (for example, TextEditor has something with codeCompletionAround).
TextEditor and friends do have a ton of class side methods with all the commands, keystrokes, and menu entries. Very important to grasp how that works. The TextMorph>>editorClass returns the editor class to use. Currently the SmalltalkEditor (yikes!)
If gets taken in TextMorph>>installEditorToReplace: priorEditor, where we get editor := self editorClass forMorph: self. digging further, we get TextEditor>>forMorph: aMorph returning
^self basicNew initWithMorph: aMorph. and ... we'll get there! ... TextEditor>>initWithMorph: aMorph super initialize.
morph := aMorph. self resetState. So, we now have both linked.
That dance occurs everytime we get something occuring to the TextMorph. >>handleEvent: anEvent will do anEvent sendTo: self and then the usual:
evt sendTo: anObject, which will handle the event with ^anObjject handleMouseUp, donw, ...
That is where we get back to the self handleInteraction: evt which calls the [editor mouseUp: evt] through the TextMorph handleInteraction. An interesting bit occurs with the TextMorph>>yellowActivity; shiftKeyState for the menus (and the PragmaMenuBuilder and strings like 'smalltalkMenu' looking into SmallTalk editor for menu entries (Class side, yellowButtonMenu and shifted friend).
That's it for editor, except we need to say a word on its lifecyle: It gets created and destroyed all the time: created with TextMorph>>hasFocus, going away with keyBoardFocusChange
Then for Paragraph, just realize that Paragraphis something to be used like; Paragraph new compose: text "Coming from the TextMorph"
style: textStyle copy "always copy these beasties" from: 1 in (0@0 extent: extX@extY); adjustRightX; ... So, the Paragraph is composing the text into an area, taking into account the styles that are in the text The TextStyle is the default style, it can be overriden by some TextAttribute.
And that's where the TextMorph>>drawOn: aCanvas comes into play. if will invoke Canvas>>paragraph: which will draw the text. This will lead us to CharacterScanner and friends (CompositionScanner) and TextComposer depending on it.
look for composeLineFrom: to: .... or composeAllLines. This will call Paragraph>>composeAll ^self multiComposeLinesFrom: firstCharIndex
to: text size delta: 0 into: OrderedCollection new "Ah, there we will end up into" priorLines: Array new atY: container top. So, it may be interesting to see how Paragraph works, but paragraph has nothing to do with Editor.
Paragraph renders the text if an editing change has to be shown display wise. But doesn't know about the Editor. TextMorph uses TextMorph>>updateFromParagraph and >>fit to do the stuff.
In CharacterScanner you can find interesting display code: CharacterScanner>>basicScanCharactersFrom: startIndex to: stopIndex in: sourceString
rightX: rightX stopConditions: stops "this one still a tad foggy to me" kern: kernDelta There is a primitive rendering a char down there. This is all for StrikeFont. I don't know how TrueType is supported but there are
As you are doing Vim keystrokes, check TextMorph>>basicKeyStroke that does the same dance as the mouse events but invokes self handleInteraction: [editor keystroke evt]
self updateFromParagraph. super keystroke: evt. So, hope this makes it all a bit clearer. All of the PluggableTextMorph story builds upon all of the above to ensure a scrolling window and widget pluggability. Which I do not care at this point since I am designing a specific UI for a game.
Phil 2012/7/18 Stéphane Ducasse <[hidden email]>
|
In reply to this post by Fernando olivero-2
I wouldn't do that for basic morphs as it would make Cairo necessary and then make completely ununderstandable what happens for laying out text for someone who wants to understand it (which is an important aspect of an open smalltalk image).
TextMorph>>onBlinkCursor leads you to Paragraph (of course since it deals with the display) onBlinkCursor "Blink the cursor"
| para | para := self paragraph ifNil:[^nil]. Time millisecondClockValue < self blinkStart ifTrue:[
"don't blink yet" ^para showCaret: para focused. ].
para showCaret: para showCaret not. para caretRect ifNotNil:[:r| self invalidRect: r].
so, para>>focused if where to look (but it is only a variable change so, you'll need to track the usage) Phil 2012/7/20 Fernando Olivero <[hidden email]> Hi Sean, you can take a look at Athens-PangoCairo (in squeaksource). |
In reply to this post by Fernando olivero-2
Hello
2012/7/20 Fernando Olivero <[hidden email]> Hi Sean, you can take a look at Athens-PangoCairo (in squeaksource). How I can try your code? Do you have ready image to play with it? I am very interested with clean and simple alternative to morphic. I want it for Presenty framework. (But I really like morphic as live user interface environment) Best regards, Denis |
So, there is the damn caret drawing code:
Paragraph>>displaySelectionInLine: line on: aCanvas
| leftX rightX w caretColor |
selectionStart ifNil: [^self]. "No selection" aCanvas isShadowDrawing ifTrue: [ ^self ]. "don't draw selection with shadow"
selectionStart = selectionStop ifTrue: ["Only show caret on line where clicked"
selectionStart textLine ~= line ifTrue: [^self]] ifFalse:
["Test entire selection before or after here" (selectionStop stringIndex < line first
or: [selectionStart stringIndex > (line last + 1)]) ifTrue: [^self]. "No selection on this line"
(selectionStop stringIndex = line first and: [selectionStop textLine ~= line]) ifTrue: [^self]. "Selection ends on line above"
(selectionStart stringIndex = (line last + 1) and: [selectionStop textLine ~= line]) ifTrue: [^self]]. "Selection begins on line below"
leftX := (selectionStart stringIndex < line first ifTrue: [line ]
ifFalse: [selectionStart ])left.
rightX := (selectionStop stringIndex > (line last + 1) or: [selectionStop stringIndex = (line last + 1)
and: [selectionStop textLine ~= line]]) ifTrue: [line right] ifFalse: [selectionStop left].
selectionStart = selectionStop ifTrue: [rightX := rightX + 1.
w := self caretWidth. caretRect := (leftX-w) @ line top corner: (rightX+w)@ line bottom.
self showCaret ifFalse:[^self]. caretColor := self insertionPointColor.
1 to: w do: [:i |
"Draw caret triangles at top and bottom" aCanvas fillRectangle: ((leftX - w + i - 1) @ (line top + i - 1)
extent: ((w - i) * 2 + 3) @ 1) color: caretColor. aCanvas fillRectangle: ((leftX - w + i - 1) @ (line bottom - i)
extent: ((w - i) * 2 + 3) @ 1) color: caretColor]. aCanvas fillRectangle: (leftX @ line top corner: rightX @ line bottom)
color: caretColor] ifFalse: [caretRect := nil.
aCanvas fillRectangle: (leftX @ line top corner: rightX @ line bottom) color: self selectionColor]
Paragraph class>>insertionPointColor has the color. I was fed up of blue, turned it red :-) This one is hardcoded and could take a hint from the selection color twiceDarker for example.
Phil 2012/7/20 Denis Kudriashov <[hidden email]> Hello Philippe Back Dramatic Performance Improvements Mob: +32(0) 478 650 140 | Fax: +32 (0) 70 408 027 Mail: [hidden email] | Web: http://philippeback.eu | Blog: http://philippeback.be High Octane SPRL rue cour Boisacq 101 1301 Bierges Belgium |
In reply to this post by Denis Kudriashov
Hi Phil. Excellent summary of the current mess!
Yes, TextMorphs are the "views" , Editors handle the insertion/selection/menu logic, and Paragraphs lay out the text. I've replaced Paragraph, with Pango Layouts to reuse a more customizable layout engine, until some kind soul rewrites completely Paragraph (and friends) to be as easy to use (and powerfull) as Pango (which i doubt it will happen in the next decade). Denis, unfortunately i had to handle other stuff related to my phd, and still couldn't release Gaucho/Shapes, I'm working on it now again. Here's a presentation i gave @ the pharo conf [1]. Glad to hear that you want to try to use it for Presently, will be out soon. [1] http://app.sliderocket.com:80/app/FullPlayer.aspx?id=fcff251e-29cd-49eb-89b3-e33349139ddf On Fri, Jul 20, 2012 at 4:26 PM, [hidden email] <[hidden email]> wrote: > So, there is the damn caret drawing code: > > Paragraph>>displaySelectionInLine: line on: aCanvas > | leftX rightX w caretColor | > selectionStart ifNil: [^self]. "No selection" > aCanvas isShadowDrawing ifTrue: [ ^self ]. "don't draw selection with shadow" > selectionStart = selectionStop > ifTrue: > ["Only show caret on line where clicked" > > selectionStart textLine ~= line ifTrue: [^self]] > ifFalse: > ["Test entire selection before or after here" > > (selectionStop stringIndex < line first > or: [selectionStart stringIndex > (line last + 1)]) ifTrue: [^self]. "No selection on this line" > (selectionStop stringIndex = line first > and: [selectionStop textLine ~= line]) ifTrue: [^self]. "Selection ends on line above" > (selectionStart stringIndex = (line last + 1) > and: [selectionStop textLine ~= line]) ifTrue: [^self]]. "Selection begins on line below" > leftX := (selectionStart stringIndex < line first > ifTrue: [line ] > ifFalse: [selectionStart ])left. > rightX := (selectionStop stringIndex > (line last + 1) or: > [selectionStop stringIndex = (line last + 1) > and: [selectionStop textLine ~= line]]) > ifTrue: [line right] > ifFalse: [selectionStop left]. > selectionStart = selectionStop > ifTrue: > [rightX := rightX + 1. > w := self caretWidth. > caretRect := (leftX-w) @ line top corner: (rightX+w)@ line bottom. > self showCaret ifFalse:[^self]. > caretColor := self insertionPointColor. > 1 to: w > do: > [:i | > "Draw caret triangles at top and bottom" > > aCanvas fillRectangle: ((leftX - w + i - 1) @ (line top + i - 1) > extent: ((w - i) * 2 + 3) @ 1) > color: caretColor. > aCanvas fillRectangle: ((leftX - w + i - 1) @ (line bottom - i) > extent: ((w - i) * 2 + 3) @ 1) > color: caretColor]. > aCanvas fillRectangle: (leftX @ line top corner: rightX @ line bottom) > color: caretColor] > ifFalse: > [caretRect := nil. > aCanvas fillRectangle: (leftX @ line top corner: rightX @ line bottom) > color: self selectionColor] > > > > > Paragraph class>>insertionPointColor has the color. I was fed up of blue, turned it red :-) > This one is hardcoded and could take a hint from the selection color twiceDarker for example. > > Phil > > 2012/7/20 Denis Kudriashov <[hidden email]<mailto:[hidden email]>> > Hello > > 2012/7/20 Fernando Olivero <[hidden email]<mailto:[hidden email]>> > Hi Sean, you can take a look at Athens-PangoCairo (in squeaksource). > > Using NativeBoost, i'm using the Pango layout library [1], and the > Pango-Cairo binding [2], to avoid laying out text using the outdated > (and messy) stuff in the image. > > Check out the classes: ParagraphDescription & AthensPangoCairoParagraph. > > I'm using them as the basis for the TextShape,LabelShape, and > EditableTextShape in Shapes / Gaucho ( using TextEditor, > SingleLineEditor ). > > Maybe somebody can do the same for Morphic? use Pango to layout the > text, and code a new TextMorph on top of it? > > How I can try your code? > Do you have ready image to play with it? > > I am very interested with clean and simple alternative to morphic. I want it for Presenty framework. > > (But I really like morphic as live user interface environment) > > Best regards, > Denis > > > > > > > -- > Philippe Back > Dramatic Performance Improvements > Mob: +32(0) 478 650 140 | Fax: +32 (0) 70 408 027 Mail: [hidden email]<mailto:[hidden email]> | Web: http://philippeback.eu | Blog: http://philippeback.be > > High Octane SPRL > rue cour Boisacq 101 > 1301 Bierges > Belgium |
In reply to this post by philippeback
Phil
Sorry for the state of the system. We are cleaning slowly. Now what would be good is that if you could enhance the class comments. Igor started to write a new paragraph (or text representation) I guess that he needs some help/feedback. Igor should be back from holiday so ping him please :). Stef > Ah, the morass into which I am currently digging... > > Well, if we look at it for a while, it becomes a tad clearer. > > PluggableTextMorph is just a shell for a TextMorph. > > The TextMorph basically displays a Text (which can be styled with TextAttributes) > > When moving into edition, there is an editor known by the TextMorph but this is not an editor like I understood it, but rather a helper object that will come handy with TextMorph>>handleInteraction: interactionBlock > > Inside handleInteraction, there is that editor and paragraph and then a call to interaction blockValue. > > And the interactionBlock is containing a bunch of various things that delegate the real editing work to the editor. > > Like in aTextMorph>>handleInteraction: [editor mouseUp: evt] > > If you then look into the editor (mostly SmalltalkEditor right now in the image), you see a quite large method for that mouseUp: evt handling. And lots of other things. > > There should be a cleanup occuring in the Editor -> TextEditor -> SmalltalkEditor hierarchy. > > The TextEditor knows a bit too much and I am currently implementing a child of TextEditor to have a simple, clean editor that does only the basics for my purpose. Once I am please with it, it may become an interesting child of Editor (maybe the TextEditor itself, with TextEditor renamed to something else (for example, TextEditor has something with codeCompletionAround). > > TextEditor and friends do have a ton of class side methods with all the commands, keystrokes, and menu entries. Very important to grasp how that works. > > The TextMorph>>editorClass returns the editor class to use. Currently the SmalltalkEditor (yikes!) > > If gets taken in TextMorph>>installEditorToReplace: priorEditor, where we get editor := self editorClass forMorph: self. > > digging further, we get TextEditor>>forMorph: aMorph returning > > ^self basicNew initWithMorph: aMorph. > > and ... we'll get there! ... TextEditor>>initWithMorph: aMorph > > super initialize. > morph := aMorph. > self resetState. > > So, we now have both linked. > > That dance occurs everytime we get something occuring to the TextMorph. > > >>handleEvent: anEvent will do anEvent sendTo: self and then the usual: > > evt sendTo: anObject, which will handle the event with ^anObjject handleMouseUp, donw, ... > > That is where we get back to the self handleInteraction: evt which calls the [editor mouseUp: evt] through the TextMorph handleInteraction. > > An interesting bit occurs with the TextMorph>>yellowActivity; shiftKeyState for the menus (and the PragmaMenuBuilder and strings like 'smalltalkMenu' looking into SmallTalk editor for menu entries (Class side, yellowButtonMenu and shifted friend). > > That's it for editor, except we need to say a word on its lifecyle: > > It gets created and destroyed all the time: created with TextMorph>>hasFocus, going away with keyBoardFocusChange > > > Then for Paragraph, just realize that Paragraphis something to be used like; > > Paragraph new > compose: text "Coming from the TextMorph" > style: textStyle copy "always copy these beasties" > from: 1 > in (0@0 extent: extX@extY); > adjustRightX; > ... > > So, the Paragraph is composing the text into an area, taking into account the styles that are in the text The TextStyle is the default style, it can be overriden by some TextAttribute. > > And that's where the TextMorph>>drawOn: aCanvas comes into play. > > if will invoke Canvas>>paragraph: which will draw the text. > > This will lead us to CharacterScanner and friends (CompositionScanner) and TextComposer depending on it. > > look for composeLineFrom: to: .... or composeAllLines. > > This will call Paragraph>>composeAll > > ^self multiComposeLinesFrom: firstCharIndex > to: text size > delta: 0 > into: OrderedCollection new "Ah, there we will end up into" > priorLines: Array new > atY: container top. > > > So, it may be interesting to see how Paragraph works, but paragraph has nothing to do with Editor. > > Paragraph renders the text if an editing change has to be shown display wise. But doesn't know about the Editor. > > TextMorph uses TextMorph>>updateFromParagraph and >>fit to do the stuff. > > In CharacterScanner you can find interesting display code: > > CharacterScanner>>basicScanCharactersFrom: startIndex > to: stopIndex > in: sourceString > rightX: rightX > stopConditions: stops "this one still a tad foggy to me" > kern: kernDelta > > There is a primitive rendering a char down there. This is all for StrikeFont. I don't know how TrueType is supported but there are > > As you are doing Vim keystrokes, check TextMorph>>basicKeyStroke that does the same dance as the mouse events but invokes > > self handleInteraction: [editor keystroke evt] > self updateFromParagraph. > super keystroke: evt. > > So, hope this makes it all a bit clearer. > > All of the PluggableTextMorph story builds upon all of the above to ensure a scrolling window and widget pluggability. Which I do not care at this point since I am designing a specific UI for a game. > > Phil > > 2012/7/18 Stéphane Ducasse <[hidden email]> > > On Jul 16, 2012, at 9:38 PM, Sean P. DeNigris wrote: > > > For VimPharo, I want to have a different cursor depending on whether a tool > > is in insert or normal mode. > > > > I tried a handful of ways, but they all failed or worked > > partially/inconsistently. Here's some of them: > > * add the state to the paragraph, but the entire paragraph gets replaced > > during the life of the tool, so the state gets lost > > * add the state to the editor, but the situation is the same > > * add the state to PluggableTextMorph, override and access it from > > TextMorphForEditView>>updateFromParagraph. This was an extreme PITA and got > > me very acquainted with the emergency evaluator. It "worked", but only after > > using the arrows a bit. > > > > Does anyone have any idea where I might hook in? > > > > <rant>I find the whole text system very confusing. What the heck does a > > paragraph know about insertion points?? A view has one paragraph object, > > even if there are several paragraphs (as understood by the rest of humanity > > as a block of text with breaks between the adjoining ones. Editors and > > Paragraphs are thrown out and replaced on a whim. I'm finding it very hard > > to understand and modify</rant> > > I got burned by that when I worked on my botanics env…. > it was terrible. > > > > > Thanks, > > Sean > > > > -- > > View this message in context: http://forum.world.st/Customizing-the-Caret-of-a-PluggableTextMorph-tp4640245.html > > Sent from the Pharo Smalltalk mailing list archive at Nabble.com. > > > > > > > |
Free forum by Nabble | Edit this page |