Today we add the InputField that is the "display part" of our Calendar.
Create and Display the Display Part
We simply want an input field as our display part (the left part of our Calendar). The superclass, ActionDisplay, says that it owns the displayPart instance variable. (We will be moving that to the artist where it really belongs, early next year) So, we'll add a new method, to our Calendar pane to create this part. The common name used in other ActionDisplay panes for this is #createDisplayPart... we'll use that name here:
You see here we do very little to make the part. Like our action part, the button, we use a fractional frame. We use the buttonWidth we created in the artist last time, and set that, negated, as the right offset. Finally, like the button, we tell the input field that it's enclosing pane is self, the Calendar.
Now all we have to do is create it. We'll just call it from our #initialize method:
Calendar>>initialize
super initialize.
self interiorDecoration: self getInteriorDecoration.
self createDisplayPart.
That's all there is to it. We can see the results if we run our example:
CalendarTest new openWindowWithCalendar
Details
If you have good eyes, you'll see that the InputField portion of our Calendar has an extra border around it. That's the interior decoration of the input field. By default, an input field has an interior decoration. In a Windows look though, the input part of a drop down has no interior decoration. Instead, the drop down, in Windows, has an interior decoration around the whole pane. We added that several steps ago. So, we need to turn off the interior decoration of the input field. Fortunately, that's simple. We just give it nil as its interior decoration:
If we run our example now, we see it looks much better. But, if we click on the input field part, it does nothing... just like the action part, we need the CalendarAgent to deal with that in it's handlerForMouseEvent: method:
Now if we open our example, it will toss a Does Not Understand on #quietlyRequestActivationFor:. We've seen this before. This means that someone (in this case our InputField) is expecting to have a keyboard processor, but doesn't. We can fix that pretty simply:
If you're paying attention to the name #setupKeyboardFor: and saying to yourself "We want to set it up FOR the display part, not self, the Calendar", you're right. The problem is in the name of the method. We'll be renaming it to #setupKeyboardFrom: early next year.
Now if we open up our example, we can click in the InputField, enter text, and even the right click copy/cut/paste menu works. We're basically done!
Pollock Plug And Play
Before we finish this posting, let's look back at how we set the interior decoration of the InputField to nil. Pollock's plug and play nature says that you can send every message to a pane at any time, and change it dynamically. But, if we look back at the interiorDecoraton: method we created a few steps ago we will notice that we can't set our Calendar's interior decoration to nil without having that method blow up.... Let's look at what it currently looks like:
As you see, if we tried to send in nil, that would die in a hurry. What we want to do is first, find out if the current interior decoration is nil, and if not, set that artists pane to nil. Then we want to test if the new decoration is nil or not, and if not, do what we did before, but if it is, we want to "unset" the displayable bounds. Finally, we want to have the pane invalidate, because, we might do that at runtime, and otherwise it won't show right away.
Here, we use the framework #borderEdgeRectangle which just answers the edge rectangle for our pane as a Zero rectangle if the pane has a border (ActionDisplay panes never do) or if it does, then that border's edgeRectangle.
Now that we've added it, let's have some fun! First, let's add an accessor to our CalendarTest for calendar:
CalendarTest>>calendar
^calendar
Open our tester example, but assign the opened object to a variable (this is automatic in VisualWorks workspaces... just do it):
tester := CalendarTest new openWindowWithCalendar
Now, in the workspace, with the example open, execute the following:
tester calendar interiorDecoration: nil
Everything still works, but the calendar no longer has the interior decoration around the combined input field an button. I leave it as an exercise for the reader to write workspace code to change it back.
The above is published as version 1.8 in the Package named "Pollock-Calendar" on the Cincom public repository.
Next time we'll start working on the calendar pane which opens when we press the button.