TextPresenter with background image

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
18 messages Options
Reply | Threaded
Open this post in threaded view
|

TextPresenter with background image

talios@gmail.com
Does anyone know if its possible to have a TextPresenter with a
background image?

I tried putting an ImageViewer behind it with the TextPresenter set to
transparant with no joy.

I'm guessing I may need to subclass the TextPresenter and override some
paint method?

Basically I want to set a faded watermark behind a multiline text entry
field.  ( and maybe also the same on a ListPresenter ).

Mark


Reply | Threaded
Open this post in threaded view
|

Re: TextPresenter with background image

Blair McGlashan-3
"Mark Derricutt" <[hidden email]> wrote in message
news:cinubh$[hidden email]...
> Does anyone know if its possible to have a TextPresenter with a background
> image?
>
> I tried putting an ImageViewer behind it with the TextPresenter set to
> transparant with no joy.
>

The standard Windows controls, with a few exceptions, do not really support
transparency....

> I'm guessing I may need to subclass the TextPresenter and override some
> paint method?
\
... however you may be able to achieve what you want by using a bitmap brush
for the background. Currently you can only specify a solid colour background
brush for controls (by setting the #backcolor aspect) in our standard
wrapper classes. We will almost certainly be adding the ability to set an
arbitrary background brush in the next version (we want to be able to
support gradient fills in particular), but in the meantime you will have to
subclass MultilineTextEdit and add the support yourself.

>...
> Basically I want to set a faded watermark behind a multiline text entry
> field.  ( and maybe also the same on a ListPresenter ).

You need to override #onColorRequired:  to answer the handle to a bitmap
brush. You will also need to stub-out the ControlView>>onEraseBackground:
implementation, which shouldn't really be there at all, so just override it
and return nil (although this is not strictly necessary if you ensure that
the backcolor is nil). This will cause the text edit control to erase its
own background, and it will then use the background brush you supply (from
your implementation of #onColorRequired:) to erase its own background,
having the effect of painting the background using a bitmap.

I did a quick and dirty experiment to try this out. First I created a Bitmap
brush in a workspace:

bmp := Bitmap fromFile: 'c:\windows\gone fishing.bmp'.
B := Brush bitmap: bmp.

Then I defined #onColorRequired: in MultlineTextEdit as follows (obviously
don't save your image after this, or delete the method first):

onColorRequired: aColorEvent
 super onColorRequired: aColorEvent.
 (aColorEvent canvas)
  brush: B;
  setBkMode: TRANSPARENT.
 ^B asParameter

Now try it out:
    MultilineTextEdit show

Try commenting out the #setBkMode: message to see what effect that has.
Anyway you will see that it basically works, although as an apparent result
of setting the background mode of the canvas to transparent it doesn't erase
on backspace (or select/deselect) so that needs some thought and further
work to see if it can be worked around.

Regards

Blair


Reply | Threaded
Open this post in threaded view
|

Re: TextPresenter with background image

talios@gmail.com
Blair McGlashan wrote:

Hi Blair, finally getting around to looking at this....

>I did a quick and dirty experiment to try this out. First I created a Bitmap
>brush in a workspace:
>  
>
I subclassed MultilineTextEdit and created the brush in #initialize and
added the #onColorRequired override, seems to be doing something but
just gives me a "not indexable" error.

11:24:09 AM, Wednesday, October 06, 2004: 'not indexable'
UndefinedObject(Object)>>errorAt:
UndefinedObject(Object)>>at:
BrushedMultilineTextEdit(View)>>baseStyle
BrushedMultilineTextEdit(View)>>parentView:
BrushedMultilineTextEdit(View)>>showShell
BrushedMultilineTextEdit class(View class)>>show

This seems to happen on any bitmap I've tried or created.  Mmmm.  
Initiallly I thought this might be something to do with image formats
but even if I try set the brush to "brush := Brush gray" I get the 'not
indexable' problem.

Did this work for you when you tried it in your quick test?

Hopefully I'll have some more time this afternoon to look at this closer...

mark


Reply | Threaded
Open this post in threaded view
|

Re: TextPresenter with background image

Randy Coulman-2
[ From your previous posts, it sounds like you're still pretty new to
Smalltalk, so I'm throwing in some extra information that may or may not
be new or useful. ]

Mark Derricutt wrote:
> I subclassed MultilineTextEdit and created the brush in #initialize and
> added the #onColorRequired override, seems to be doing something but
> just gives me a "not indexable" error.
>

First, note this:

> 11:24:09 AM, Wednesday, October 06, 2004: 'not indexable'
> UndefinedObject(Object)>>errorAt:
> UndefinedObject(Object)>>at:
   ^^^^^^^^^^^^^^^

> BrushedMultilineTextEdit(View)>>baseStyle
> BrushedMultilineTextEdit(View)>>parentView:
> BrushedMultilineTextEdit(View)>>showShell
> BrushedMultilineTextEdit class(View class)>>show
>

I still forget to look at the object that's reporting the error a lot.
When the object is "UndefinedObject", that means that something you're
working with is nil.  Normally, you get a "message not understood"
because you've sent a message that nil doesn't understand, but at: works
differently; hence, the "not indexable" error.

Anyway, View>>baseStyle just sends a message to creationStyle, which is
an instance variable.  Looking at uses of it, it should be set in
View>>initialize.  Either the call to "self defaultStyle" there is
returning nil (I didn't look further to see if that was possible), or
(more likely, if it was me doing the work) your
BrushedMultilineTextEdit>>initialize method doesn't call super initialize.

If the second one isn't the problem, I've hopefully left you a couple of
other bread crumbs to follow.

Randy
--
Randy Coulman
NOTE: Reply-to: address is spam-guarded.  Reassemble the following to
reply directly:
rcoulman at charter dot net


Reply | Threaded
Open this post in threaded view
|

Re: TextPresenter with background image

talios@gmail.com
Randy Coulman wrote:

> [ From your previous posts, it sounds like you're still pretty new to
> Smalltalk, so I'm throwing in some extra information that may or may
> not be new or useful. ]

Yep - have been reading alot about Smalltalk over the past year or so
but actually really been using it for the past month or two.  I'm
enjoying it - but also finding bits and pieces hellishly fustrating.  
Although that mostly seems to be a) COM b) MVP c) Windows in general ;p

> I still forget to look at the object that's reporting the error a lot.
> When the object is "UndefinedObject", that means that something you're
> working with is nil.  Normally, you get a "message not understood"

Doh - as you say, I did forget to look at WHAT was thrown the error...  
*sigh*

> your BrushedMultilineTextEdit>>initialize method doesn't call super
> initialize.

And there we have it....  added the call to super and voila - perfection ;-)


Reply | Threaded
Open this post in threaded view
|

Re: TextPresenter with background image

talios@gmail.com
Mark Derricutt wrote:

> And there we have it....  added the call to super and voila -
> perfection ;-)

-almost- have it.  The class works fine when doing
"BrushedMultilineTextEdit show" in a transcript, but after opening my
view and mutating the existing MultilineTextEdit to the new one I see my
bitmap in the view composer ( yay ) but when I a) test the view b) save
it and run it in my app I just see the normal MultilineTextEdit.

Mmmmm.


Reply | Threaded
Open this post in threaded view
|

Re: TextPresenter with background image

talios@gmail.com
Mark Derricutt wrote:

> -almost- have it.  The class works fine when doing
> "BrushedMultilineTextEdit show" in a transcript, but after opening my
> view and mutating the existing MultilineTextEdit to the new one I see
> my bitmap in the view composer ( yay ) but when I a) test the view b)
> save it and run it in my app I just see the normal

Ok, just replying to myself once more for googlesake, the Mutated
version -is- working, as I can add "self halt" to #onColourRequired and
see it trip up all the time.  However, what -isn't- being run is
#initialize.

Hmmmmmm.  Time to go hunting.


Reply | Threaded
Open this post in threaded view
|

Re: TextPresenter with background image

talios@gmail.com
Mark Derricutt wrote:

> Ok, just replying to myself once more for googlesake, the Mutated
> version -is- working, as I can add "self halt" to #onColourRequired
> and see it trip up all the time.  However, what -isn't- being run is
> #initialize.

Score.  Switching from loading my BMP in #initialize to loading it in
#onViewOpened and she's away laughing ;-)

Mark


Reply | Threaded
Open this post in threaded view
|

Re: TextPresenter with background image

Schwab,Wilhelm K
Mark,

> Score.  Switching from loading my BMP in #initialize to loading it in
> #onViewOpened and she's away laughing ;-)

One more thing to check: does it work if the view/presenter is open when
you save the image and then restart Dolphin?  IIRC, #onViewOpened is not
called in that scenario.  Sorry if I am sending you in pursuit of a wild
aquatic fowl.

Have a good one,

Bill


--
Wilhelm K. Schwab, Ph.D.
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: TextPresenter with background image

talios@gmail.com
Bill Schwab wrote:

> One more thing to check: does it work if the view/presenter is open
> when you save the image and then restart Dolphin?  IIRC, #onViewOpened
> is not called in that scenario.  Sorry if I am sending you in pursuit
> of a wild aquatic fowl.
>
> Have a good one,
>
Not sure - just running off for a bus home so will have to check once I
get to the other end of the city :).


Reply | Threaded
Open this post in threaded view
|

Re: TextPresenter with background image

Blair McGlashan-3
In reply to this post by talios@gmail.com
"Mark Derricutt" <[hidden email]> wrote in message
news:cjvrq4$[hidden email]...
> Mark Derricutt wrote:
>
>> Ok, just replying to myself once more for googlesake, the Mutated
>> version -is- working, as I can add "self halt" to #onColourRequired and
>> see it trip up all the time.  However, what -isn't- being run is
>> #initialize.
>
> Score.  Switching from loading my BMP in #initialize to loading it in
> #onViewOpened and she's away laughing ;-)

Yes, #initialize is only run the first time a View instance is created.
Subsequently to that one is effectively deserialising a pre-initialised
instance. Depending on how you've created your Bitmap, however, you might
not need to recreate it since it may, if loaded from a resource or file, be
able to recreate itself on demand.

Try this example in a workspace.

    bmp := Bitmap fromFile: 'c:\windows\Gone fishing.bmp'.
    bmp "Ctrl+I - inspect the bitmap and verify the image has loaded. Close
the inspector."
    ... Now save the image, exit and restart"
    bmp basicHandle    "Ctrl+D - this will be nil on restart"
    bmp "Ctrl+I - inspect the bitmpa, and verify that the image has
reloaded."
    bmp basicHandle    "Ctrl+D - this will now be non-nil"

If your bitmap is created by drawing onto a Bitmap canvas, then it is not
persistent, and will not be valid on restarting an image. For example if you
snapshot the desktop like this:

bmp := Bitmap displayCompatibleWithExtent: View desktop extent.
bmp canvas bitBlt: View desktop canvas rectangle: View desktop rectangle to:
0@0 rop: 13369376 "SRCCOPY".

Then on restart the bitmap will be blank because not attempt is currently
made to persist the bits of a bitmap in the image file.

Regards

Blair


Reply | Threaded
Open this post in threaded view
|

Re: TextPresenter with background image

talios@gmail.com
In reply to this post by Blair McGlashan-3
Blair McGlashan wrote:

>Anyway you will see that it basically works, although as an apparent result
>of setting the background mode of the canvas to transparent it doesn't erase
>on backspace (or select/deselect) so that needs some thought and further
>work to see if it can be worked around.
>  
>
Blair - I have a work around for this, when responding to #keyPressed: I
now have the following:

    BrushedMultilineEdit>>processKeyPress: aKeyEvent
        aKeyEvent wParam = 8 ifTrue: [self view refreshContents].

However, this causes the whole view to flicker and redraw in a somewhat
nasty fashion.

I notice if I changed this to "contentPresenter view refreshContents"
nothing happened; no error but no refresh either.  I didn't seem to see
any refresh methods on the Presenter itself ( or its ancesters but I
might be blind here ).

It's currently better than NOT having the refresh and having text draw
over itself, but I'm sure the flicker will drive me insane ;p  Any ideas?

Mark


Reply | Threaded
Open this post in threaded view
|

Re: TextPresenter with background image

Chris Uppal-3
Mark Derricutt wrote:

> It's currently better than NOT having the refresh and having text draw
> over itself, but I'm sure the flicker will drive me insane ;p  Any ideas?

You might be able to do something clever by either providing your own paint
procedure and/or using the restricted form of #invalidate:, but I wanted to
suggest something simpler.  Would it be adequate if you just removed the
background[*] while the control has focus (i.e put a <self hasFocus> test into
the #onColorRequired code), and do <self invalidate> in #onKillFocus, so that
the background is restored when the user moves away from the control ?  I'd set
a normal" background colour that was roughly similar to the bitmap's average to
minimise the visual impact of the change.

You could even  claim that it was done that way to make editing easier ;-)

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: TextPresenter with background image

talios@gmail.com
Chris Uppal wrote:

>You might be able to do something clever by either providing your own paint
>procedure and/or using the restricted form of #invalidate:, but I wanted to
>suggest something simpler.  Would it be adequate if you just removed the
>  
>
I remember from my old delphi does making use of the LockWindowsUpdate()
method to refuse updating of the display untill you'd done everything
but that was only really usefull when removing say 1000+ items from a
listview/listbox etc. etc.  So probably wouldn't really be appropriate here.

>background[*] while the control has focus (i.e put a <self hasFocus> test into
>the #onColorRequired code), and do <self invalidate> in #onKillFocus, so that
>the background is restored when the user moves away from the control ?  I'd set
>  
>
>You could even  claim that it was done that way to make editing easier ;-)
>  
>
It's possible.  The whole reason for putting an image behind the text
area is for product branding.  Originally my bosses wanted a solid hunky
image plonked on the dialog which looked somewhat yucky, and out of
place, so I thought of having this faded/watermark faintly behind the
edit area which would provide branding space, and not be obtrusive.

You're idea does have good merit thou, I could leave the image there
untill they start typing there message and remove it then.  mmmm.  I'll
have to toy with that in the morning when I get back to the office.

mark


Reply | Threaded
Open this post in threaded view
|

Re: TextPresenter with background image

Blair McGlashan-3
In reply to this post by talios@gmail.com
"Mark Derricutt" <[hidden email]> wrote in message
news:ck2akg$[hidden email]...

> Blair McGlashan wrote:
>
>>Anyway you will see that it basically works, although as an apparent
>>result of setting the background mode of the canvas to transparent it
>>doesn't erase on backspace (or select/deselect) so that needs some thought
>>and further work to see if it can be worked around.
>>
> Blair - I have a work around for this, when responding to #keyPressed: I
> now have the following:
>
>    BrushedMultilineEdit>>processKeyPress: aKeyEvent
>        aKeyEvent wParam = 8 ifTrue: [self view refreshContents].
>
> However, this causes the whole view to flicker and redraw in a somewhat
> nasty fashion.

Yes I can imagine.

>
> I notice if I changed this to "contentPresenter view refreshContents"
> nothing happened; no error but no refresh either.  I didn't seem to see
> any refresh methods on the Presenter itself ( or its ancesters but I might
> be blind here ).

Well without knowing what contentPresenter is, it is difficult to guess at
why ... :-)

>
> It's currently better than NOT having the refresh and having text draw
> over itself, but I'm sure the flicker will drive me insane ;p  Any ideas?

I'll have a think, but as a start point you could try invalidating only the
area occupied by the text. This isn't perhaps as hard as it sounds because
the #calculateExtent method will give you back the correct height for the
text (plus a blank line) in the control at its current width:

    m := MultilineTextEdit show.
    m text: 'Blah de blah blah blah, de blah blah blah, blahdeblah'.
    "Now run this next line separately"
    m canvas fillRectangle: m clientRectangle brush: Brush black.
    "When you evaluate this next line, you should see that only the text and
a blank line gets restored"
    m invalidateRect: (0@0 extent: m calculateExtent).

This might help until someone can think of a better way - its probably worth
trawling VB (or general Windows) programming tip sites, since the same issue
would apply to anyone attempting to use a textured (bitmap) brush as the
background of a multiline edit control.

Regards

Blair


Reply | Threaded
Open this post in threaded view
|

Re: TextPresenter with background image

talios@gmail.com
Blair McGlashan wrote:

>    "When you evaluate this next line, you should see that only the text and
>a blank line gets restored"
>    m invalidateRect: (0@0 extent: m calculateExtent).
>  
>
Excellent - that works a treat, more so than the refresh at least, still
a bit of flicker.  I was thinking of invalidate as I'd used that years
ago in delphi when doing similar things, sadly years of java/linux have
hidden win32 api foo deep in the recesses of the mind....  they're
slowly starting to resurface - but I'm not sure if I really want them too :P


Reply | Threaded
Open this post in threaded view
|

Re: TextPresenter with background image

Chris Uppal-3
Mark Derricutt wrote:

> >    m invalidateRect: (0@0 extent: m calculateExtent).
> >
> >
> Excellent - that works a treat, more so than the refresh at least, still
> a bit of flicker.

Just a thought, but using

    self invalidateRect: (...) erase: false

might reduce the flicker further -- if it works at all...

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: TextPresenter with background image

Blair McGlashan-3
In reply to this post by talios@gmail.com
"Mark Derricutt" <[hidden email]> wrote in message
news:ck4bh0$[hidden email]...

> Blair McGlashan wrote:
>
>>    "When you evaluate this next line, you should see that only the text
>> and a blank line gets restored"
>>    m invalidateRect: (0@0 extent: m calculateExtent).
>>
> Excellent - that works a treat, more so than the refresh at least, still a
> bit of flicker.  I was thinking of invalidate as I'd used that years ago
> in delphi when doing similar things, sadly years of java/linux have hidden
> win32 api foo deep in the recesses of the mind....  they're slowly
> starting to resurface - but I'm not sure if I really want them too :P

Hmmm, getting the EDIT control to work correctly with any background other
than a solid colour is really quite a tricky problem. Superficially it is
easy to get it to paint on a textured background, but there are a lot of
redisplay issues when editing, and also scrolling. I had a couple of goes at
it over the last couple of days, and found a couple of helpful ideas on
"advanced VB" sites, although the implementations were a bit of a mess (just
as much a the fault of VB as the programmers that created them mind you).
Anyway I have finally come up with a solution that paints correctly and does
not exhibit flicker. Scrolling is a bit slower than normal, but usable.
Anyway I hope it satisfies your requirement, and that it is of general
utility. The package can be downloaded from:

http://object-arts.com/Lib/Update/Dolphin/5.1/MTEWithImage.zip

Please let me know what you think.

Regards

Blair