The top level navigation in Glamorous Toolkit is called Glamorous World
. It is implemented in the GToolkit-World
package and consists of a custom window space GtWorld
BlSpace subclass: #GtWorld
instanceVariableNames: 'worldElement'
classVariableNames: ''
package: 'GToolkit-World-UI'
with GtWorldElement
GtWorldTabElement subclass: #GtWorldElement
instanceVariableNames: 'spotterDropdown subSpaceDropdown notificationsDropdown announcer'
classVariableNames: 'IsWorldSpotterPreviewDisplayed WorldSpotterSize'
package: 'GToolkit-World-UI'
as its root element. The interface consists of a tab group with a GtHome
BlElement subclass: #GtHome
instanceVariableNames: 'sectionsHolder feedElement notificationsElement knowledgeBase'
classVariableNames: ''
package: 'GToolkit-World-UI'
default tab available at all times. Additional tabs can be closed and moved around by the means of drag and drop.
It is possible to rearrange tabs in the world by drag and dropping them. Each tab except the home one is made draggable by adding a custom drag handler instantiated by GtWorldTabElement>>#createTabDragHandler
createTabDragHandler
^ BlDragHandler new
restrictDragToHorizontal;
liftItem: [ :aSourceElement |
BlDragItem new
sourceElement: aSourceElement;
domainObject: aSourceElement model;
stencil: [ :aDragItem |
(self createBaseTab: aDragItem domainObject)
select;
opacity: 0.85 ] ]
. The tab group widget then creates a drop handler BrGlamorousSpaceTabGroupAptitude>>#createTabDropHandler
createTabDropHandler
^ BlDropHandler new
acceptOnlyFromThisElement;
whenDragOverDo: [ :anItemsDraggedOverEvent |
| container locationElement position |
container := anItemsDraggedOverEvent currentTarget.
locationElement := container
childWithId: #'drop-area--drop-location'
ifFound: [ :anElement | anElement ]
ifNone: [ | anElement |
anElement := BlElement new
background: container theme default primaryBorderColor;
width: 2;
elevation: (BlRelativeElevation elevation: 100);
constraintsDo: [ :c |
c ignoreByLayout.
c vertical matchParent ].
container addChild: anElement as: #'drop-area--drop-location'.
anElement ].
position := anItemsDraggedOverEvent position x.
self
dragOverTo: position
in: container
withMarker: locationElement ];
whenDragLeftDo: [ :anItemsLeftEvent | anItemsLeftEvent currentTarget removeChildNamed: #'drop-area--drop-location' ];
whenHorizontalDroppedDo: [ :anItemsDroppedEvent :anIndex |
self
dropTabs: (anItemsDroppedEvent items
collect: [ :eachDragItem | eachDragItem sourceElement ])
at: anIndex ]
that is responsible for interactivity and detection of a tab index where drop should occur. Eventually, the actuall tab movement happens in BrGlamorousSpaceTabGroupAptitude>>#dropTabs:at:
dropTabs: aCollectionOfTabs at: anIndex
anIndex = 0
ifTrue: [ ^ self ].
self
widgetDo: [ :aTabGroup |
| targetTabIndex |
targetTabIndex := anIndex.
aCollectionOfTabs do: [ :eachTab | aTabGroup moveTab: eachTab atCursor: targetTabIndex ].
aCollectionOfTabs ifNotEmpty: [ :theTabs | theTabs first select ] ]
.