The Artima Developer Community
Sponsored Link

Agile Buzz Forum
Pollock Changes - Part 8

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
Pollock Changes - Part 8 Posted: Sep 21, 2005 11:17 AM
Reply to this message Reply

This post originated from an RSS feed registered with Agile Buzz by James Robertson.
Original Post: Pollock Changes - Part 8
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 get into how Menus are refactored, and their new use of Actions.

Menu Grouping

Menus now no longer use numbers to do grouping of menu items. Instead, Menus are composed. A Menu may contain any number of Menus and MenuItems, and may be nested to any arbitrary depth.

Grouping is determined by a Menu being in a Menu. It's probably easier for me to give an example. Let's take the standard Popup menu that is in our existing Wrapper Workspace. It has 7 groups:

	1 - Accept, Format
	2 - DoIt, PrintIt, InspectIt, DebugIt
	3 - FileIn, Explain
	4 - Cut, Copy, Paste
	5 - Find, Replace
	6 - Hardcopy
	7 - Cancel

With the new Menu structure, each of these can be a Menu. The popup menu itself can thus be just 7 Menus. Or, it could be the first 6 as menus, and then a single "Cancel" menu item. Or, it could be an Accept menu item, a Format menu item, then 2 - 6 as Menus, then a single "Cancel" menu item.

Or (and this is where nesting can come in), we could do it like this (detailed):

	1 - Accept (item)
	2 - Format (item)
	3 - (Menu)
		1 - (Menu)
			1 - DoIt (item)
			2 - PrintIt (item)
			3 - InspectIt (item)
			4 - DebugIt (item)
		2 - FileIn (item)
		3 - Explain (item)
	4 - (Menu)
		1 - Cut (item)
		2 - Copy (item)
		3 - Paste (item)
	5 - (Menu)
		1 - Find (item)
		2 - Replace (item)
	6 - (Menu)
		1 - Hardcopy (item)
	7 -	Cancel (item)

The point is, a group is defined as being started as a Menu, and ends with items in that menu. More importantly, it means you can reuse Menus. For instance the "It" Menu can be reused in other panes, as well as the "Find/Replace" and "Edit" menus.

The API

Of course, composing menus means that we need some APIs to help out. First, adding and removing menu items:

	addMenuItem: <aMenuOrMenuItem>
	addMenuItem: <aMenuOrMenuItem> afterItemKey: <anObject>
	addMenuItem: <aMenuOrMenuItem> afterMenuItem: <aMenuItem>
	addMenuItem: <aMenuOrMenuItem> beforeItemKey: <anObject>
	addMenuItem: <aMenuOrMenuItem> beforeMenuItem: <aMenuItem>

	removeMenuItem: <aMenuOrMenuItem>
	removeMenuItemsWithItemKeys: <nameKeyCollection>
	removeMenuItemWithItemKey: <anObject>

Then, adding and removing whole Menus:

	addMenu: <aMenu>
	addMenu: <aMenu> afterItemKey: <anObject>
	addMenu: <aMenu> afterMenuItem: <aMenuItem>
	addMenu: <aMenu> beforeItemKey: <anObject>
	addMenu: <aMenu> beforeMenuItem: <aMenuItem>

	removeMenu: <aMenuOrMenuItem>
	removeMenuWithID: <anObject>

And finally, adding and removing a collection of Menus and/or Menu Items:

	addMenuParts: <menuPartsCollection> afterItemKey: <anObject>
	addMenuParts: <menuPartsCollection> afterMenuItem: <aMenuItem>
	addMenuParts: <menuPartsCollection> beforeItemKey: <anObject>
	addMenuParts: <menuPartsCollection> beforeMenuItem: <aMenuItem>

	removeMenuParts: <menuPartsCollection>

Before we go on, you might catch that the "addMenuItem:..." API has as a parameter "aMenuOrMenuItem." That is because the "addMenu:..." API is sugar. Adding a single Menu or MenuItem (what I call a "Menu Part") is identical under the hood.

Interestingly the old #menuItems and #groupSizes are both still there, and do what they used to do. #groupSizes does an inject recursive iteration and gives you a collection of integers, each representing how many items in each group. #menuItems similarly recurses and gives you a flattened collection of Menu Items.

Under the hood, a Menu has in effect renamed the "menuItems" iVar to "menuParts", and indeed, there is a new #menuParts method that gives you the raw value it holds. The #menuItems method returns what you used to get in Wrapper: A collection of the items, all flattened out without regard to the grouping.

Hot Keys -> Keystrokes

Next, instead of the old "Wrapper" way of defining "hotkeys" for menu items, we use the new Keystroke as described previously. Thus, the old Wrapper like shortcutKey: and shortcutModifiers: API is gone, and replaced with:

	keystroke: <aKeystroke>
	keystroke: <aKeystroke> onPlatforms: <aCollectionOfPlatformSymbols>
	keystroke: <aKeystroke> onPlatformsExcept: <aCollectionOfPlatformSymbols>

As we see, this matches the Action/Keymap framework previously discussed.

Exmaple

Now, you cam define a menu, such as:

	<aMenuItem>
		keystroke: (Keystroke ctrl: $a) onPlatformsExcept: #(#mac);
		keystroke: (Keystroke command: $a) onPlatforms: #(#mac)

And it will Display and Act appropriate to the platform!

Actions

To complete the move to Action/Keymap, instead of #action which were either symbols or blocks or message sends, the MenuItem has changed to "Actions" and instead uses #actionID(:). It will then use the action id to look in the pane, or user interface etc., to get the Action object, and execute it. All APIs have changed from action(:) to actionID(:).

Surprise

While putting this all together, I was surprised at something. Lets say we had a window with two InputFields. If we clicked on the top one, and went to a main menu's Paste menu item (for instance) that menu item had no idea where it was supposed to paste to!

Honest!

This is in Wrapper too!!!

So, I added a twist to Pollock's MenuItem's use of Actions. If you define an action like this:

	Action
		id: <someID>
		selector: <someSelectorWithColon>
		receiver: <someReceiver>
		argument: #lastActivePane

(Note the explicit symbol for the final argument is #lastActivePane) Then, at execute time, the pane that had focus just before the menu was started will be dynamically replaced by the symbol #lastActivePane as the argument.

I created tests for this, which you can see in the "tests - Actions" of the MenuBarTest class in PollockTesting.

Under the hood, the Pollock EventDispatcher captures the initial and last non-menu focus pane, and there is an API on AbstractPane and Windows #lastActivePane, which allows you to access this if you want.

A Detail

While rooting around, I found a small bug in AbstractPane displayOn: where it wasn't obeying the rules of visibility or clipping. This is now fixed.

More To Come!

That concludes the description of the changes from the 7.3.1 release of Pollock to the public release of 6.13.0

But...

About a week or so ago, I was doing my regular updating of the internal work, but our internal repository was down. Being all ADD and all, I couldn't wait for the repository to come back up, so I instead published the newest version on the public repository!

Version 6.16.0

Since it's there, you can indeed use it. Therefore, next time I'll document the further changes between what was in 6.13.0 and what is now the newest publicly available version.

And So It Goes
Sames

Read: Pollock Changes - Part 8

Topic: Updated Silt Files Previous Topic   Next Topic Topic: Complexity = Scalability?

Sponsored Links



Google
  Web Artima.com   

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