Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Trying to make a simple RTF editor

28 views
Skip to first unread message

Graham Dicker

unread,
Apr 21, 2012, 9:59:06 AM4/21/12
to
Coud someone please help me with editing an Rich Text file. I created a
couple of classes to edit an RTF and it almost works but fails in various
ways depending on what I last changed in the source code. Some efforts
result in the text saving properly but without the most recent changes.
Sometimes it saves properly if I step through the code slowly.

The Rich Text file is loaded by this code:

editInternalMemo: aProfilerMenuItem

| components tempfilename t |

aProfilerMenuItem hasInternalMemo ifTrue: [
components := File splitPath: self filename.
tempfilename := (components at: 1), (components at: 2)
, (aProfilerMenuItem parameter2) , '.rtf'.
t := DFMemoModel new load: tempfilename.
RTFShell showOn: t.
].

and below are the two classes called RTFShell and DFMemoModel that I am
trying to use to edit and save it.

Thank you

Graham Dicker


"Filed out from Dolphin Smalltalk X6.1"!

Shell subclass: #RTFShell
instanceVariableNames: 'rtfedit'
classVariableNames: ''
poolDictionaries: ''
classInstanceVariableNames: ''!
RTFShell guid: (GUID fromString: '{4D51A493-A823-486E-87F8-598760604098}')!
RTFShell comment: ''!
!RTFShell categoriesForClass!MVP-Presenters! !
!RTFShell methodsFor!

createComponents
"Private - Create the presenters contained by the receiver"

super createComponents.
rtfedit := self add: RichTextPresenter new name: 'editor'
!

createSchematicWiring

self
when: #closeRequested:
send: #onCloseRequested:
to: self.
!

model: aDFMemoModel

super model: aDFMemoModel.
rtfedit model: aDFMemoModel text.
!

onCloseRequested: aShellView

| choice |

rtfedit isModified ifTrue: [
choice := MessageBox confirm: 'File is modified.
Save?' caption: 'SVPanel'.
choice ifTrue: [ self save ].
].!

save

"self model text: (rtfedit model value asParameter)."
self model save: (rtfedit model value asParameter).
rtfedit isModified: false.
! !
!RTFShell categoriesFor: #createComponents!private! !
!RTFShell categoriesFor: #createSchematicWiring!public! !
!RTFShell categoriesFor: #model:!public! !
!RTFShell categoriesFor: #onCloseRequested:!public! !
!RTFShell categoriesFor: #save!public! !

!RTFShell class methodsFor!

defaultModel
"Answer a default model to be assigned to the receiver when it
is initialized."

^DFMemoModel new
!

resource_Default_view
"Answer the literal data from which the 'Default view' resource
can be reconstituted.
DO NOT EDIT OR RECATEGORIZE THIS METHOD.

If you wish to modify this resource evaluate:
ViewComposer openOn: (ResourceIdentifier class: self selector:
#resource_Default_view)
"

^#(#'!!STL' 3 788558 10 ##(Smalltalk.STBViewProxy) 8
##(Smalltalk.ShellView) 98 27 0 0 98 2 27131905 131073 416 0 524550
##(Smalltalk.ColorRef) 8 4278190080 0 551 0 0 0 416 1180166
##(Smalltalk.ProportionalLayout) 234 240 98 0 32 234 256 98 2 410 8
##(Smalltalk.RichTextEdit) 98 18 0 416 98 2 8 1140920644 1025 624 0 482 8
4278190080 0 7 265030 4 ##(Smalltalk.Menu) 0 16 98 10 984134 2
##(Smalltalk.CommandMenuItem) 1 1180998 4 ##(Smalltalk.CommandDescription)
8 #chooseSelectionFont 8 '&Font...' 1 1 0 0 0 983366 1
##(Smalltalk.DividerMenuItem) 4097 786 1 818 8 #bePlain 8 '&Plain' 1 1 0 0
0 786 1 818 8 #toggleBold 8 '&Bold' 1 1 0 0 0 786 1 818 8 #toggleItalic 8
'&Italic' 1 1 0 0 0 786 1 818 8 #toggleUnderlined 8 '&Underlined' 1 1 0 0 0
882 4097 738 0 16 98 3 786 1025 818 8 #alignParagraphLeft 8 '&Left' 1 1 0 0
0 786 1025 818 8 #alignParagraphCenter 8 '&Centre' 1 1 0 0 0 786 1025 818 8
#alignParagraphRight 8 '&Right' 1 1 0 0 0 8 '&Align' 0 1 0 0 0 0 0 882 4097
786 1 818 8 #chooseSelectionColor 8 '&Colour...' 1 1 0 0 0 8 '' 0 1 0 0 0 0
0 0 0 624 0 8 1961168360 852486 ##(Smalltalk.NullConverter) 0 0 9 0 655622
##(Smalltalk.EDITSTREAM) 8 #[0 0 0 0 0 0 0 0 48 0 2 1] 983302
##(Smalltalk.MessageSequence) 202 208 98 6 721670 ##(Smalltalk.MessageSend)
8 #createAt:extent: 98 2 328198 ##(Smalltalk.Point) 1 1 1746 1185 709 624
1682 8 #contextMenu: 98 1 752 624 1682 8 #text: 98 1 524550
##(Smalltalk.RichText) 8
'{\rtf1\ansi\ansicpg1252\deff0\deflang2057{\fonttbl{\f0\froman Times New
Roman;}}
\viewkind4\uc1\pard\f0\fs22
\par }
' 624 1682 8 #selectionRange: 98 1 525062 ##(Smalltalk.Interval) 3 1 3 624
1682 8 #isTextModified: 98 1 32 624 1682 8 #resetCharFormat 576 624 983302
##(Smalltalk.WINDOWPLACEMENT) 8 #[44 0 0 0 0 0 0 0 1 0 0 0 255 255 255 255
255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 80 2 0 0 98
1 0 0] 98 0 1746 193 193 0 27 8 'editor' 0 461638 4 ##(Smalltalk.MenuBar) 0
16 98 1 738 0 16 98 1 786 1 818 8 #save 8 'Save' 1 1 0 0 0 8 'File' 0
134217729 0 0 37399 0 0 8 '' 0 134217729 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0
1618 202 208 98 2 1682 1712 98 2 1746 2559 21 1746 1201 801 416 1682 8
#updateMenuBar 576 416 2098 8 #[44 0 0 0 0 0 0 0 0 0 0 0 255 255 255 255 255
255 255 255 255 255 255 255 255 255 255 255 255 4 0 0 10 0 0 0 87 7 0 0 154
1 0 0] 98 1 624 2160 0 27 )! !
!RTFShell class categoriesFor: #defaultModel!public! !
!RTFShell class categoriesFor: #resource_Default_view!public!resources-
views! !



"Filed out from Dolphin Smalltalk X6.1"!

Object subclass: #DFMemoModel
instanceVariableNames: 'text filename'
classVariableNames: ''
poolDictionaries: ''
classInstanceVariableNames: ''!
DFMemoModel guid: (GUID fromString: '{C39D9C9F-
A485-4949-8103-80BC12FF1703}')!
DFMemoModel comment: ''!
!DFMemoModel categoriesForClass!Kernel-Objects! !
!DFMemoModel methodsFor!

initialize

text := String new asRichText.
!

load: aFilename

| stream |

filename := aFilename.
stream := FileStream read: aFilename text: true.
text := stream setToEnd; contents.
stream close.!

save

filename notNil ifTrue: [ | stream |
stream := FileStream write: filename text: true.
stream nextPutAll: text.
stream close.
]
!

save: aString

filename notNil ifTrue: [ | stream |
stream := FileStream write: filename text: true.
stream nextPutAll: aString.
stream close.
]
!

text
^text asRichText
!

text: anObject
text := anObject! !
!DFMemoModel categoriesFor: #initialize!public! !
!DFMemoModel categoriesFor: #load:!public! !
!DFMemoModel categoriesFor: #save!public! !
!DFMemoModel categoriesFor: #save:!public! !
!DFMemoModel categoriesFor: #text!accessing!public! !
!DFMemoModel categoriesFor: #text:!accessing!public! !

!DFMemoModel class methodsFor!

new

^super new initialize
! !
!DFMemoModel class categoriesFor: #new!public! !

IanB

unread,
Apr 22, 2012, 2:33:25 AM4/22/12
to
Graham,

I haven't had time to analyse your code in _any_ detail, but one thing
looks a bit wrong and could be causing your problems.

In DFMemoModel you have

initialize
text := String new asRichText.

That answers an instance of the RichText class. However, when you
load the text you have

load: aFilename
[]
stream := FileStream read: aFilename text: true.
text := stream setToEnd; contents.
[]

which replaces the RichText instance above with a simple String.

Try something like

text := RichText fromString: stream contents

Have you tried using the WordPad sample application that comes with
Dolphin? That might do what you want anyway, and the code might point
you in the right direction as regards the RichText class.

FWIW, I have a deployable rich text editor that you are welcome to
have a look at / use. It's a bit more complex as it uses it's own
RichText class that wraps the latest Windows RichEdit control that
comes with Windows Vista (IIRC) and above.

Ian
--
The From and ReplyTo addresses are valid

Dolphin goodies and newsgroup archive - http://www.idb.me.uk

Graham Dicker

unread,
Apr 22, 2012, 3:40:18 AM4/22/12
to
IanB wrote:

> Graham,
>
> I haven't had time to analyse your code in _any_ detail, but one thing
> looks a bit wrong and could be causing your problems.
>
> In DFMemoModel you have
>
> initialize
> text := String new asRichText.

At the stage I wrote that, I had no idea what I was doing.

>
> That answers an instance of the RichText class. However, when you
> load the text you have
>
> load: aFilename
> []
> stream := FileStream read: aFilename text: true.
> text := stream setToEnd; contents.
> []
>
> which replaces the RichText instance above with a simple String.

I hacked the "stream setToEnd; contents." bit from the WordPad sample.

>
> Try something like
>
> text := RichText fromString: stream contents
>
> Have you tried using the WordPad sample application that comes with
> Dolphin? That might do what you want anyway, and the code might point
> you in the right direction as regards the RichText class.

Yes I tried that first of all. When I tested it in the development system it
worked just fine but in the deployed version when the WordPad window was
closed all the other opened windows in the application closed too! I was
also a little worried that a full featured editor like WordPad might allow
the user to do things that would cause problems for the accounts program
that creates the RTFs.

>
> FWIW, I have a deployable rich text editor that you are welcome to
> have a look at / use. It's a bit more complex as it uses it's own
> RichText class that wraps the latest Windows RichEdit control that
> comes with Windows Vista (IIRC) and above.

That sounds good. My customer will be using this app on all versions of
Windows from XP onwards. My only development machine is XP SP3. Will it work
on XP?

Thanks very much

--
Graham Dicker

IanB

unread,
Apr 22, 2012, 4:44:41 AM4/22/12
to
Graham,

Can I ask what you are trying to accomplish? Is just to display
RichText documents, or do you want to be able to edit them and then
resave?

>That sounds good. My customer will be using this app on all versions of
>Windows from XP onwards. My only development machine is XP SP3. Will it work
>on XP?

I don't think so. It uses the latest version of the Windows control,
and as I recall that only came with Vista (and 7 and 8).

The following might give you some ideas (workspace code)

s := Shell show.
rt := (RichTextEdit new)
parentView: s view;
create;
yourself.
s view layoutManager: BorderLayout new.
rt arrangement: #center.
s view addSubView: rt.
fn := FileOpenDialog showModalOn: '*.rtf'.
fs := FileStream read: fn.
[rt readRtfFrom: fs] ensure: [fs close].

The above should enable you to open a rtf file and edit it. It might
take a bit more to get scrolling working, #canVScroll and #canHScroll
don't seem to work on a RichTextEdit, at least in the simplified way
I'm using it here.

fn := FileSaveDialog showModalOn: '*.rtf'.
fs := FileStream write: fn.
[fs nextPutAll: rt text rtf] ensure: [fs close]

Evaluating this in the _same_ workspace should resave the file. NB
the #rtf in the last line is marked as private but I can't remember
the clean way to do it.

It must be 6 or 7 years, if not more, since I delved into the murky
world of RichTextEdits; I had forgotten how much brain ache they could
cause :-(

Graham Dicker

unread,
Apr 22, 2012, 9:03:59 AM4/22/12
to
Ian thanks very much for your help. I got it going OK now, with a
combination of your suggestions and some more reading through the WordPad
code.

Scrolling wasn't a problem; canVScroll worked OK and horizontal scrolling
isn't required.

The biggest puzzle was why it wasn't saving my changes - answer: you have to
set something called updatePerChar in the RichTextEdit. Took a long time to
spot that.

Cheers

--
Graham Dicker
0 new messages