This post originated from an RSS feed registered with Agile Buzz
by James Robertson.
Original Post: How To Create A Custom Widget - MacOSX Blue Haze
Feed Title: Pollock
Feed URL: http://www.cincomsmalltalk.com/rssBlog/pollock-rss.xml
Feed Description: Pollock - the next VW GUI
Today we deal with the rather complex task of the blue haze, aka the selection rectangle, for the MacOSX look of the Calendar, and the effect it has on other looks.
The Problem
In the MacOSX look, the blue haze around any pane, even when it isn't visible actually takes up visible area inside the bounds of the pane. So, when with other looks, we ask for a pane that uses a layout rectangle of 10 @ 10 corner: 110 @ 40, the full area we see, whether selected or not is 100 @ 30. But, on the MacOSX look, when not selected, the pane takes up an area of 96 @ 26, and visibly, looks to have an origin of 12 @ 12.
Therefore, when in the MacOSX look, we have to tell it to tell the action and display parts to be smaller, and at a different origin than stipulated.
The Resolution - Action Part
First, we add a couple of constant methods to our artists:
This forces the offset of the frame to be inset 2 from the top, right and bottom. The left (the edge next to the input field) is already offset. Now if we have the MacOSX look on (using our look changer: PollockWorkspaceWork new openLookSwitcherWindow) and open our tester (CalendarTest new openWindowWithCalendar) we see our action part is a bit smaller than the input part, but otherwise all is well.
The Resolution - Display Part
We have to do a similar change to our #createDisplayPart:
We in the main method, we do the usual clipping stuff. And then we call our #selectionRectangleFrom: method. The comment basically says it all... the point is that we can't draw ON the edge of a clipped rectangle. From there on, we use the #checkBoxTraversalHilite color, which has been set up for us to be the blue haze color by the MacOSXLookPolicy.
We draw the outer rectangle, then the inner rectangle, thus giving us a two wide paint. Then we get a new rectangle that is inset 2 from the outermost rectangle. With this rectangle, we paint the left two corners (origin and bottomLeft). This gives the illusion of the edge of the input field being a bit rounded when selected. It's a minor detail but that much better that we take care to match. Between those corer dots, we fill in the "rounded" area of the right top and right bottom (corner) where the button part does not display.
Now the standard CalendarArtist doesn't display a selection rectangle, so we have to write a do nothing method there:
CalendarArtist>>displaySelectionRectangleOn: aGraphicsContext in: aRectangle
"By default, I don't do this, subclasses may"
Finally, we add to our standard #displayOn: method, in CalendarArtist:
There we go. Now we open our tester, click on the Calendar and....
Mouse Handling
Yup, the haze didn't show! What went wrong?
The hint is in the "isSelected ifTrue:" of our #displayOn:. As we said WAY long ago, and dealt with in our #handlerForMouseEvent: of the CalendarAgent, the Calendar pane itself doesn't do keyboard handling and passes all mouse events to it's underlying display and action panes (the input field and button). What we have to do now is to change our #handlerForMouseEvent: method, so when it sees a mouse pressed event, it tells the Calendar it is selected.
Basically, we check if the event can even go to the part, and if so, and it is a button press, we tell ourselves to be selected. Now, if we open our tester and click on the action part (the button) of our Calendar, the blue haze comes on. Then if we click in the display part (the input field)...
Wrapper Hall Of Fame
The haze didn't show. In fact, it disappeared! What's wrong now?!?!
One of the unfortunate side effect of using Wrapper's Keyboard Processor and Event Dispatcher sub-frameworks, is that when our input field gets focus, one of the thing it does is send deactivate to the Calendar pane itself... actually, it's agent via the controller.
This little bit of horror will be done away with in Pollock Feature Set 2, when we write a new Keyboard Processor that handles independent tab order, and get rid of Controllers all together with a whole new Event Dispatcher sub-framework.
In the mean time, we have to add a bit of Wrapper compatibility to our otherwise pure work. We simply tell our agent to ignore the #deactivate method:
CalendarAgent>>deactivate
"Do Nothing because we still use Wrapper's Event Dispatcher and Keyboard Processor sub-frameworks"
This is mostly safe, but will cause us some small problems later. But later is later, so for now, it does what we want.
Now, if we open our tester, and click either on the action part (the button) or the display part (the input field) we get our blue haze.
The above is published as version 1.21 in the Package named "Pollock-Calendar" on the Cincom public repository.
If we change the look, to either Windows or Motif... Well, it seems that our pane stays the small size, and other uglies creep in. Next time, we'll deal with how to make sure everything looks right, with the right sizes of all sub-components, when we change the looks.