The Artima Developer Community
Sponsored Link

Agile Buzz Forum
How To Create A Custom Widget - InputField and Navigation Button Decorations

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
James Robertson

Posts: 29924
Nickname: jarober61
Registered: Jun, 2003

David Buck, Smalltalker at large
How To Create A Custom Widget - InputField and Navigation Button Decorations Posted: Dec 15, 2004 2:26 PM
Reply to this message Reply

This post originated from an RSS feed registered with Agile Buzz by James Robertson.
Original Post: How To Create A Custom Widget - InputField and Navigation Button Decorations
Feed Title: Pollock
Feed URL: http://www.cincomsmalltalk.com/rssBlog/pollock-rss.xml
Feed Description: Pollock - the next VW GUI
Latest Agile Buzz Posts
Latest Agile Buzz Posts by James Robertson
Latest Posts From Pollock

Advertisement

Today we'll dynamically change the input field part's border for Motif, and the button look for the navigation buttons. Also note that somehow I lost some code when publishing the 1.17 version for the calendar part decoration. This is fixed in today's publish.


Display Part (InputField) Decoration

Last time we left off with the border around the whole Calendar changing properly, but the display part wasn't changing it's border. First we start with some tests:

	CalendarTest>>testChangeLookMotifToWindowsDisplayPartDecoration
		self shouldnt: [MotifLookPolicy installLookPreferences] raise: Error.
		self openWindowWithCalendar.
		self shouldnt: [Win98LookPolicy installLookPreferences] raise: Error.
		self should: [calendar displayPart hasInteriorDecoration not]

	CalendarTest>>testChangeLookWindowsToMotifDisplayPartDecoration
		self shouldnt: [Win98LookPolicy installLookPreferences] raise: Error.
		self openWindowWithCalendar.
		self shouldnt: [MotifLookPolicy installLookPreferences] raise: Error.
		self should: [calendar displayPart hasInteriorDecoration]

Only one will pass (the Motif to Windows test), because when we create the display part, we give it a nil interior decoration. Like with the calendar decoration, we add methods to the border policies for the border we want to have.

	BorderPolicy class>>calendarInputFieldDecoration
		^nil

	MotifBorderPolicy class>>calendarInputFieldDecoration
		^self inputFieldDecoration

We reuse the standard input field decoration for Motif, but answer nil for Windows. Now, let's change how we create our display part:

	Calendar>>createDisplayPart
		displayPart := InputField new.
		displayPart frame: (FractionalFrame 
			fractionLeft: 0
			top: 0
			right: 1
			bottom: 1).
		displayPart frame rightOffset: [self artist buttonWidth negated].
		displayPart interiorDecoration: self borderPolicyClass calendarInputFieldDecoration.
		displayPart setEnclosingPane: self.
		self isOpen
			ifTrue: [displayPart setupKeyboardFor: self]
			ifFalse: [self configure: #setupKeyboardFor: for: displayPart argument: self].
		displayPart when: #clicked send: #triggerEvent: to: self with: #clicked.
		displayPart when: #rightClicked send: #triggerEvent: to: self with: #rightClicked.
		displayPart when: #doubleClicked send: #triggerEvent: to: self with: #doubleClicked.
		displayPart when: #aboutToLoseFocus send: #triggerEvent: to: self with: #aboutToLoseFocus.
		displayPart when: #losingFocus send: #triggerEvent: to: self with: #losingFocus.
		displayPart agent doNotIncludeInTabList.
		self when: #gettingFocus send: #activate to: displayPart.
		self when: #losingFocus send: #deactivate to: displayPart

Now, if we open our look changing utility (PollockWorkspaceWork new openLookSwitcherWindow) select the Windows look and then open our tester (CalendarTest new openWindowWithCalendar) it looks fine as it did before. Then, if we close the tester, switch to Motif look and open our tester, it looks good now. But if we change from one to the other, it just stays where it was. One more change will fix that with a simple change to our #replaceArtistWithThatFrom: method:

	Calendar>>replaceArtistWithThatFrom: aWidgetPolicy
		| newArtist oldArtist |
		newArtist := aWidgetPolicy calendarArtistClass on: self.
		self artist giveAttributesTo: newArtist.
		self displayPart interiorDecoration: aWidgetPolicy borderPolicyClass calendarInputFieldDecoration.
		oldArtist := artist.
		artist := newArtist.
		oldArtist release.

Note how we send our message here to the passed in widget policy. Changing from the Motif to the Windows look, or visa versa, no matter which we start from, looks great. Also, all of our tests run properly.


Navigation Buttons In Motif

Once we change to the Motif look, the basic Calendar looks ok, but when we open the drop down, the navigation buttons look nasty. We have some choices here. We could simply say that the buttons should have no interior decoration at all. This is how our example drop down looked. But that's too easy a choice, and frankly, doesn't help the learning process here.

So we add, like before, some new methods to our border policies:

	BorderPolicy class>>calendarNavigationButtonDecoration
		^self buttonDecoration

	MotifBorderPolicy>>calendarNavigationButtonDecoration
		^self dropDownListButtonDecoration

We're re-using the standard button decoration in the base border policy, and then, for Motif, we're using the same border that we use on the button portion of our main Calendar. All that is left now is to tell the buttons, when we create them, what decorations to use:

	CalendarAgent>>addNavigationButtonsTo: aForm 
		| button |
		button := Button new.
		button frame: self leftButtonsFrame.
		(button frame)
			rightOffset: 18;
			bottomOffset: 18.
		button interiorDecoration: pane borderPolicyClass calendarNavigationButtonDecoration.
		button addComponent: self previousYearButtonIcon.
		button when: #pressed send: #decrementYear to: self.
		aForm addComponent: button.
		button := Button new.
		button frame: self leftButtonsFrame.
		(button frame)
			leftOffset: 19;
			rightOffset: 37;
			bottomOffset: 18.
		button interiorDecoration: pane borderPolicyClass calendarNavigationButtonDecoration.
		button addComponent: self previousMonthButtonIcon.
		button when: #pressed send: #decrementMonth to: self.
		aForm addComponent: button.
		button := Button new.
		button frame: self rightButtonsFrame.
		(button frame)
			leftOffset: -18;
			bottomOffset: 18.
		button interiorDecoration: pane borderPolicyClass calendarNavigationButtonDecoration.
		button addComponent: self nextYearButtonIcon.
		button when: #pressed send: #incrementYear to: self.
		aForm addComponent: button.
		button := Button new.
		button frame: self rightButtonsFrame.
		(button frame)
			rightOffset: -19;
			leftOffset: -37;
			bottomOffset: 18.
		button interiorDecoration: pane borderPolicyClass calendarNavigationButtonDecoration.
		button addComponent: self nextMonthButtonIcon.
		button when: #pressed send: #incrementMonth to: self.
		aForm addComponent: button

As we see, the drop down is only open when the button is pressed, so we don't have to worry about dynamic changing the drop down. None the less, we want our drop down to look good. And now, when in the Motif look, it does.

The above is published as version 1.18 in the Package named "Pollock-Calendar" on the Cincom public repository.

Next time, we'll clean up the Grid in the Motif look's drop down so that all the elements fit properly without any partial cell display on the right or bottom of the grid.


And So It Goes
Sames

Read: How To Create A Custom Widget - InputField and Navigation Button Decorations

Topic: Smalltalk and Version Control, again Previous Topic   Next Topic Topic: The first day ends

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use