Adding Images to ListView

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

Adding Images to ListView

Barry Carr-4
Hi,

Could anyone tell me, or point me at an example of how you add an image to
a column in a ListView.

I know it has something to do with ImageMangers and Images, but its not
clear to me how you get a bitmap into an instance of an Image - it looks
like you have to use a resource file. Is this correct?

I've looked at the code for MethodBrowser to see how that did it but got
totally thrown when I saw the getImageBlock aspect for one of the
ListViewColumns refer to IconicListAbstract. How does this work?

Thanks very much.

Regards

Barry Carr
Ixian Software Components Ltd
Blairgowrie
Perthshire


Reply | Threaded
Open this post in threaded view
|

Re: Adding Images to ListView

Bill Schwab
Barry,

> I know it has something to do with ImageMangers and Images, but its not
> clear to me how you get a bitmap into an instance of an Image - it looks
> like you have to use a resource file. Is this correct?

I don't pretend to understand image lists (fortunately I don't have to<g>),
but they seem to work in terms of indexes returned by #imageIndex.


> I've looked at the code for MethodBrowser to see how that did it but got
> totally thrown when I saw the getImageBlock aspect for one of the
> ListViewColumns refer to IconicListAbstract. How does this work?

This is a common (and clever) "trick".  In various places that view
resources would be tempted to hang onto a block, you will instead find a
class.  If you look at the class (class vs. instance tab in the CHB), you
will find #value, #value:, #value:value: as appropriate.  The resulting view
resources are smaller because they don't have to hold a block, only an STB
proxy for the class.

Have a good one,

Bill

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


Reply | Threaded
Open this post in threaded view
|

Re: Adding Images to ListView

Ian Bartholomew-17
In reply to this post by Barry Carr-4
Barry,

> I know it has something to do with ImageMangers and Images, but its not
> clear to me how you get a bitmap into an instance of an Image - it looks
> like you have to use a resource file. Is this correct?

For a ListView I think you have to use icons rather than bitmaps (but could
easily be wrong). Try the following in a workspace [1]

"When you add an icon to the image manager it answers an Integer, a unique
value for the icon *in the current image*"

index1 := IconImageManager current addImage: (Icon fromFile: 'c:\x.ico').
index2 := IconImageManager current addImage: (Icon fromFile: 'c:\y.ico').

"You can then use this index as the value answered by the #getImageBlock:."

lp := ListPresenter show: 'Enhanced list view'.
lp view getImageBlock: [:o |
    (o includes: $e)
        ifTrue: [index1]
        ifFalse: [index2]].
lp list: #('one' 'two' 'three')

In actual use I would expect the #getImageBlock: argument to be an instance
of a class and to interrogate that for the imageIndex to use. Something like
[2] ...

lp view getImageBlock: [:myObject | myObject imageIndex]

then...

MyObjectClass>>imageIndex
    self useImage1
        ifTrue: [self imageIndex1]
        ifFalse: [self imageIndex2]

MyObjectClass>>imageIndex1
    ^cachedIndexForImage1
        ifNil: [cachedIndexForImage1 := Icon fromFile: 'blah']
        ifNotNil: [:arg | arg]

You get the idea :-)

You can also interrogate the IconImageManager for an index ...

(Icon fromFile: 'c:\x.ico') imageIndex
or
IconImageManager current indexOfImage: (Icon fromFile: 'c:\x.ico').

... but I've usually found it easier to remember it for myself.

Ian

[1] I think the following is normally equivalent to the above but it might
be preferable in some circumstances (???)

lp := ListPresenter show: 'Enhanced list view'.
index1 := lp view imageManager addImage: (Icon fromFile: 'c:\x.ico').
index2 := lp view imageManager addImage: (Icon fromFile: 'c:\y.ico').
lp view getImageBlock: [:o |
    (o includes: $e)
        ifTrue: [index1]
        ifFalse: [index2]].
lp list: #('one' 'two' 'three')

[2] I'd probably use a Message rather than a block but that would just
complicate things here.


Reply | Threaded
Open this post in threaded view
|

Re: Adding Images to ListView

Blair McGlashan
"Ian Bartholomew" <[hidden email]> wrote in message
news:O0Dh9.8402$J47.644995@stones...
> Barry,
>
> > I know it has something to do with ImageMangers and Images, but its not
> > clear to me how you get a bitmap into an instance of an Image - it looks
> > like you have to use a resource file. Is this correct?
>
> For a ListView I think you have to use icons rather than bitmaps (but
could
> easily be wrong). ....

It is generally easier to use Icons than Bitmaps, and the results will
probably be more satisfactory, but it is not essential. The issue is how to
create the "mask" for the transparent background areas of the image.
ImageManagers have a way to do this for bitmaps which involves choosing a
colour to be treated as transparent. The addition of images to the image
manage is double-dispatched, so it does not matter whether you add bitmaps
or icons.

An example of the use of bitmaps with a list view can be seen in the
Active-X Control Browser's "New Control" dialog, which displays the toolbox
bitmaps registered for each control alongside its description. The code that
sets this up can be seen in AXControlSite class>>chooseControl:

Regards

Blair


Reply | Threaded
Open this post in threaded view
|

Re: Adding Images to ListView

Barry Carr-4
In reply to this post by Barry Carr-4
Gentlemen,

My aplogies for not responding sooner. Thank you for your help with my
ListView porblem. I've got it sorted now and have a deeper understanding of
what going on, always useful. However, I do have another question. On
ListViewColumn how are the following aspects used?
   
    getContentBlock - obviously, this returns the underlying object that    
                     is used in column, but when would you need it?

    customDrawBlock - does this allow you to implement an "owner-draw"    
                     listview (as Delphi programmers would call it)? If    
                     so, could someone point me at an example please.

Thanks once again for your help.

Regards

Barry Carr
Ixian Software Components Ltd
Blairgowrie
Perthshire


Reply | Threaded
Open this post in threaded view
|

Re: Adding Images to ListView

Ian Bartholomew-17
Barry,

>               However, I do have another question. On
> ListViewColumn how are the following aspects used?
>
>     getContentBlock - obviously, this returns the underlying object that
>               is used in column, but when would you need it?

Displaying an object as an item in a ListView is a two stage operation -
1) The #getContentsBlock: is evaluated with the object in the appropriate
position in the ListModel as the block's argument.
2) The object answered by this block evaluation is then used as the argument
for #getTextBlock:, #getImageBlock: etc.

The main reason to use it is to make the creation of the ListView easier. It
enables you to avoid having to write specific handlers for #getTextBlock:
and the others if the default blocks will suffice.  For example - you have a
ListView displaying MyObjects and the first column in this ListView shows
the result of sending #first to each of the MyObjects. You might end up with

getTextBlock := [:o | o first displayString]
getImageBlock := [:o | o first icon]
sortBlock := [:a :b | a first <= b first]

As these three block all perform the default operations (see
IconicListAbstract class>>value, BasicListAbstract class>>value and
SortedCollection class>>value:value:) you could leave all the above as
defaults and just use ...

getContentsBlock := [:o | o first]

... as the object passed to the default equivalent of all of the previous
blocks will then be the one answered by the #getContentsBlock.

>     customDrawBlock - does this allow you to implement an "owner-draw"
>               listview (as Delphi programmers would call it)? If
>               so, could someone point me at an example please.

Pass.  Steve Waring did some work on this, there is a thread from early 2000
in the archive, but I'm not sure about the current state.

Regards
    Ian


Reply | Threaded
Open this post in threaded view
|

Re: Adding Images to ListView

Barry Carr-4
Hi Ian,

Thanks very much - I truly have learnt something there. I've just been
using getTextBlock

Cheers

Barry


Reply | Threaded
Open this post in threaded view
|

Re: Adding Images to ListView

Stefan Schmiedl
In reply to this post by Barry Carr-4
On Mon, 23 Sep 2002 09:49:15 +0000 (UTC),
Barry Carr <[hidden email]> wrote:
>
>     customDrawBlock - does this allow you to implement an "owner-draw"    
>              listview (as Delphi programmers would call it)? If    
>              so, could someone point me at an example please.

ho hum ... I don't know what "owner-draw" in Delphi does, but here
is what I did in a MultipleSelectionListView with 13 ListViewColumns
in its columnsList. The respective customDrawBlocks are

1.  nil
2.  nil
3.  [ :item | item backcolor: (RGB red: 255 green: 230 blue: 230) ]
4.  nil
5.  [ :item | item backcolor: (RGB red: 230 green: 255 blue: 230) ]
6.  nil
7.  nil
8.  [ :item | item backcolor: (RGB red: 255 green: 255 blue: 230) ]
9.  nil
10. nil
11. [ :item | item backcolor: (RGB red: 230 green: 230 blue: 255) ]
12. nil
13. nil

The columns have the following background colors:

1.  white
2.  white
3.  red
4.  red
5.  green
6.  green
7.  green
8.  yellow
9.  yellow
10. yellow
11. blue
12. blue
13. blue

I don't know whether that's the right way to do it, but at least
it works.

HTH
s.


Reply | Threaded
Open this post in threaded view
|

Re: Adding Images to ListView

Barry Carr-4
> ho hum ... I don't know what "owner-draw" in Delphi does, but here
> is what I did in a MultipleSelectionListView with 13 ListViewColumns
> in its columnsList. The respective customDrawBlocks are
>
> 1.  nil
> 2.  nil
> 3.  [ :item | item backcolor: (RGB red: 255 green: 230 blue: 230) ]
> 4.  nil
> 5.  [ :item | item backcolor: (RGB red: 230 green: 255 blue: 230) ]
> 6.  nil
> 7.  nil
> 8.  [ :item | item backcolor: (RGB red: 255 green: 255 blue: 230) ]
> 9.  nil
> 10. nil
> 11. [ :item | item backcolor: (RGB red: 230 green: 230 blue: 255) ]
> 12. nil
> 13. nil
>
> The columns have the following background colors:
>
> 1.  white
> 2.  white
> 3.  red
> 4.  red
> 5.  green
> 6.  green
> 7.  green
> 8.  yellow
> 9.  yellow
> 10. yellow
> 11. blue
> 12. blue
> 13. blue
>
> I don't know whether that's the right way to do it, but at least
> it works.
>
> HTH
> s.
 
Hi Stefan,

Thanks for the tip. It does seem similar to Delphi's owner draw controls.

Cheers

Barry