524 lines
14 KiB
Smalltalk
524 lines
14 KiB
Smalltalk
"
|
|
Please comment me using the following template inspired by Class Responsibility Collaborator (CRC) design:
|
|
|
|
I'm the graphical user interface for grafoscopio. I'm using Spec.
|
|
|
|
My main responsability is to provide grafoscopio with graphical widgets and other elements to manipulate grafoscopio trees, helping with common task of storing, opening and manipulating trees.
|
|
|
|
"
|
|
Class {
|
|
#name : #GrafoscopioGUI,
|
|
#superclass : #DynamicComposableModel,
|
|
#instVars : [
|
|
'windowMainMenu',
|
|
'tree',
|
|
'nodeHeader',
|
|
'nodeBody',
|
|
'headerRefreshProcess',
|
|
'selected'
|
|
],
|
|
#category : #'Grafoscopio-UI'
|
|
}
|
|
|
|
{ #category : #'as yet unclassified' }
|
|
GrafoscopioGUI class >> defaultSpec [
|
|
<spec: #default>
|
|
|
|
^ SpecLayout composed
|
|
newColumn: [ :mainWindow |
|
|
mainWindow
|
|
newRow: [:menu |
|
|
menu add: #windowMainMenu
|
|
] height: 35;
|
|
newRow: [:outlineView |
|
|
outlineView
|
|
newColumn: [ :treePart |
|
|
treePart
|
|
newRow: [:tree | tree add: #tree];
|
|
addSplitter;
|
|
newRow: [:nodeHeader | nodeHeader add: #nodeHeader] height: 30
|
|
] right: 0.7;
|
|
addSplitter;
|
|
newColumn: [ :nodePart |
|
|
nodePart add: #nodeBody] left: 0.3.
|
|
].
|
|
];
|
|
yourself
|
|
]
|
|
|
|
{ #category : #examples }
|
|
GrafoscopioGUI class >> exampleBootstrapDynamicUI1 [
|
|
"Starting from an example UI from the Spec-Glamour, to customize towards the grafoscopio
|
|
UI and get some ideas"
|
|
|
|
|notebook leftUpperPanel leftPanel treeBrowser |
|
|
|
|
"Creating a notebook-tree with dummy data"
|
|
notebook := GrafoscopioNode new becomeDefaultTestTree.
|
|
|
|
"Defining the tree roots part"
|
|
leftUpperPanel := DynamicComposableModel new.
|
|
leftUpperPanel instantiateModels: #(tree TreeModel).
|
|
leftUpperPanel tree
|
|
roots: notebook children;
|
|
childrenBlock: [:node | node children ];
|
|
displayBlock: [:node | node title ].
|
|
leftUpperPanel layout: (SpecLayout composed
|
|
add: #tree;
|
|
yourself).
|
|
"to debug upto here uncomment the next line, and comment all other 'openWithSpec' ones"
|
|
"leftUpperPanel openWithSpec."
|
|
|
|
"Integrating the previous tree with the node header and creating the body according to
|
|
the tags on the node"
|
|
leftPanel := DynamicComposableModel new.
|
|
leftPanel assign: leftUpperPanel to: #roots.
|
|
leftPanel instantiateModels: #(header TextInputFieldModel).
|
|
treeBrowser := DynamicComposableModel new.
|
|
leftUpperPanel tree
|
|
whenSelectedItemChanged: [:node |
|
|
node
|
|
ifNil:[
|
|
leftPanel header text: ''.
|
|
treeBrowser instantiateModels: #(body TextModel).
|
|
Transcript show: 'Nada que mostrar', String cr]
|
|
ifNotNil: [
|
|
leftPanel header text: (leftUpperPanel tree selectedItem content header).
|
|
leftUpperPanel tree selectedItem content tags = 'código'
|
|
ifTrue: [
|
|
treeBrowser instantiateModels: #(body GlamourPresentationModel).
|
|
Transcript show: 'I am code', String cr.
|
|
Transcript show: treeBrowser body asString, String cr.
|
|
]
|
|
ifFalse: [
|
|
treeBrowser instantiateModels: #(body TextModel).
|
|
treeBrowser body text: (leftUpperPanel tree selectedItem content body).
|
|
Transcript show: 'I am NOT code', String cr.
|
|
Transcript show: treeBrowser body asString, String cr.
|
|
]
|
|
]
|
|
].
|
|
leftPanel layout:
|
|
(SpecLayout composed
|
|
newColumn: [:column |
|
|
column
|
|
add: #roots;
|
|
add: #header height: 35];
|
|
yourself).
|
|
|
|
"Integrating the previous tree with node body content"
|
|
treeBrowser assign: leftPanel to: #leftTree.
|
|
treeBrowser layout:
|
|
(SpecLayout composed
|
|
newRow: [:r | r add: #leftTree; add: #body ];
|
|
yourself
|
|
).
|
|
treeBrowser openWithSpec.
|
|
]
|
|
|
|
{ #category : #examples }
|
|
GrafoscopioGUI class >> exampleBootstrapDynamicUI2 [
|
|
"Starting from an example UI from the Spec-Glamour, to customize towards the grafoscopio
|
|
UI and get some ideas"
|
|
|
|
|notebook leftUpperPanel leftPanel treeBrowser |
|
|
|
|
"Creating a notebook-tree with dummy data"
|
|
notebook := GrafoscopioNode new becomeDefaultTestTree.
|
|
|
|
"Defining the tree roots part"
|
|
leftUpperPanel := DynamicComposableModel new.
|
|
leftUpperPanel instantiateModels: #(tree TreeModel).
|
|
leftUpperPanel tree
|
|
roots: notebook children;
|
|
childrenBlock: [:node | node children ];
|
|
displayBlock: [:node | node title ].
|
|
leftUpperPanel layout: (SpecLayout composed
|
|
add: #tree;
|
|
yourself).
|
|
"to debug upto here uncomment the next line, and comment all other 'openWithSpec' ones"
|
|
"leftUpperPanel openWithSpec."
|
|
|
|
"Integrating the previous tree with the node header and creating the body according to
|
|
the tags on the node"
|
|
leftPanel := DynamicComposableModel new.
|
|
leftPanel assign: leftUpperPanel to: #roots.
|
|
leftPanel instantiateModels: #(header TextInputFieldModel).
|
|
treeBrowser := DynamicComposableModel new.
|
|
leftUpperPanel tree
|
|
whenSelectedItemChanged: [:node |
|
|
node
|
|
ifNil:[
|
|
leftPanel header text: ''.
|
|
treeBrowser instantiateModels: #(body TextModel).
|
|
Transcript show: 'Nada que mostrar', String cr]
|
|
ifNotNil: [
|
|
leftPanel header text: (leftUpperPanel tree selectedItem content header).
|
|
leftUpperPanel tree selectedItem content tags = 'código'
|
|
ifTrue: [
|
|
treeBrowser instantiateModels: #(body GlamourPresentationModel).
|
|
treeBrowser assign: leftPanel to: #leftTree.
|
|
treeBrowser layout:
|
|
(SpecLayout composed
|
|
newRow: [:r | r add: #leftTree; add: #body ];
|
|
yourself
|
|
).
|
|
Transcript show: 'I am code', String cr.
|
|
Transcript show: treeBrowser body asString, String cr.
|
|
]
|
|
ifFalse: [
|
|
treeBrowser instantiateModels: #(body TextModel).
|
|
treeBrowser body text: (leftUpperPanel tree selectedItem content body).
|
|
treeBrowser assign: leftPanel to: #leftTree.
|
|
treeBrowser layout:
|
|
(SpecLayout composed
|
|
newRow: [:r | r add: #leftTree; add: #body ];
|
|
yourself
|
|
).
|
|
Transcript show: 'I am NOT code', String cr.
|
|
Transcript show: treeBrowser body asString, String cr.
|
|
]
|
|
]
|
|
].
|
|
leftPanel layout:
|
|
(SpecLayout composed
|
|
newColumn: [:column |
|
|
column
|
|
add: #roots;
|
|
add: #header height: 35];
|
|
yourself).
|
|
|
|
"Integrating the previous tree with node body content"
|
|
treeBrowser openWithSpec.
|
|
]
|
|
|
|
{ #category : #examples }
|
|
GrafoscopioGUI class >> exampleBootstrapUI [
|
|
"Starting from an example UI from the Spec-Glamour, to customize towards the grafoscopio
|
|
UI and get some ideas"
|
|
|
|
|ui lay notebook |
|
|
|
|
ui := DynamicComposableModel new.
|
|
ui title: 'new | Grafoscopio'.
|
|
ui instantiateModels: #(
|
|
tree TreeModel
|
|
header TextInputFieldModel
|
|
bodyWhenMarkup TextModel
|
|
bodyWhenCode GlamourPresentationModel).
|
|
notebook := GrafoscopioNode new becomeDefaultTestTree.
|
|
ui tree
|
|
roots: notebook children;
|
|
childrenBlock: [:node | node children];
|
|
displayBlock: [:node | node title ].
|
|
|
|
lay := SpecLayout composed
|
|
newRow: [:row |
|
|
row
|
|
newColumn: [:column |
|
|
column
|
|
newRow: #tree top: 0.2;
|
|
addHSplitter;
|
|
newRow: #header bottom: 0.8] right: 0.7;
|
|
addVSplitter;
|
|
newColumn: #bodyWhenCode];
|
|
yourself.
|
|
|
|
ui openWithSpecLayout: lay.
|
|
]
|
|
|
|
{ #category : #initialization }
|
|
GrafoscopioGUI >> initializePresenter [
|
|
tree.
|
|
nodeHeader acceptBlock: [ :text|
|
|
tree selectedItem
|
|
ifNotNil: [:x |
|
|
x content: text.
|
|
self updateTree
|
|
]
|
|
]
|
|
]
|
|
|
|
{ #category : #initialization }
|
|
GrafoscopioGUI >> initializeWidgets [
|
|
|
|
"Buils graphical interface elements"
|
|
|
|
windowMainMenu := self windowMainMenu.
|
|
tree := self tree.
|
|
nodeHeader := self newTextInput.
|
|
nodeBody :=
|
|
tree selectedItem
|
|
ifNotNil: [ self updateBody ]
|
|
ifNil: [nodeBody := self newText].
|
|
windowMainMenu applyTo: self.
|
|
self focusOrder
|
|
add: windowMainMenu;
|
|
add: tree;
|
|
add: nodeHeader;
|
|
add: nodeBody.
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
GrafoscopioGUI >> nodeBody [
|
|
^ nodeBody
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
GrafoscopioGUI >> nodeBody: anObject [
|
|
nodeBody := anObject
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
GrafoscopioGUI >> nodeHeader [
|
|
^ nodeHeader
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
GrafoscopioGUI >> nodeHeader: anObject [
|
|
nodeHeader := anObject
|
|
]
|
|
|
|
{ #category : #'ui-building' }
|
|
GrafoscopioGUI >> notebookSubMenu [
|
|
|
|
^ MenuModel new
|
|
addGroup: [ :group |
|
|
group addItem: [ :item |
|
|
item
|
|
name: 'Guardar';
|
|
icon: Smalltalk ui icons smallSaveIcon;
|
|
shortcut: $s command;
|
|
action: [ self inform: 'Guardar | Por implementar ...' ] ].
|
|
group addItem: [ :item |
|
|
item
|
|
name: 'Guardar como...';
|
|
icon: Smalltalk ui icons smallSaveAsIcon;
|
|
action: [ self inform: 'Guardar | Por implementar ...' ] ].
|
|
group addItem: [ :item |
|
|
item
|
|
name: 'Exportar como html';
|
|
icon: Smalltalk ui icons smallWindowIcon;
|
|
action: [ self inform: 'Por implementar ...' ] ].
|
|
group addItem: [ :item |
|
|
item
|
|
name: 'Exportar como pdf';
|
|
icon: Smalltalk ui icons smallPrintIcon;
|
|
action: [ self inform: 'Por implementar ...' ] ].
|
|
group addItem: [ :item |
|
|
item
|
|
name: 'Ver html';
|
|
icon: Smalltalk ui icons smallInspectItIcon;
|
|
action: [ self inform: 'Por implementar ...' ] ].
|
|
group addItem: [ :item |
|
|
item
|
|
name: 'Ver pdf';
|
|
icon: Smalltalk ui icons smallInspectItIcon;
|
|
action: [ self inform: 'Por implementar ...' ] ] ]
|
|
|
|
]
|
|
|
|
{ #category : #'ui-building' }
|
|
GrafoscopioGUI >> proyectSubMenu [
|
|
|
|
^ MenuModel new
|
|
addGroup: [ :group |
|
|
group addItem: [ :item |
|
|
item
|
|
name: 'Activar repositorio remoto...';
|
|
icon: Smalltalk ui icons smallPushpinIcon;
|
|
action: [ self inform: 'Por implementar ...' ] ].
|
|
group addItem: [ :item |
|
|
item
|
|
name: 'Activar repositorio local...';
|
|
icon: Smalltalk ui icons homeIcon;
|
|
action: [ self inform: 'Por implementar ...' ] ].
|
|
group addItem: [ :item |
|
|
item
|
|
name: 'Agregar archivo...';
|
|
icon: Smalltalk ui icons newerPackagesAvailableIcon;
|
|
action: [ self inform: 'Por implementar ...' ] ].
|
|
group addItem: [ :item |
|
|
item
|
|
name: 'Eliminar archivo...';
|
|
icon: Smalltalk ui icons packageDeleteIcon;
|
|
action: [ self inform: 'Por implementar ...' ] ].
|
|
group addItem: [ :item |
|
|
item
|
|
name: 'Enviar al histórico';
|
|
icon: Smalltalk ui icons smallScreenshotIcon;
|
|
action: [ self inform: 'Por implementar ...' ] ].
|
|
group addItem: [ :item |
|
|
item
|
|
name: 'Acreditarse';
|
|
icon: Smalltalk ui icons userIcon;
|
|
action: [ self inform: 'Por implementar ...' ] ] ]
|
|
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
GrafoscopioGUI >> selected [
|
|
^ selected value
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
GrafoscopioGUI >> selected: aBoolean [
|
|
selected value: aBoolean
|
|
]
|
|
|
|
{ #category : #api }
|
|
GrafoscopioGUI >> title [
|
|
^ ' | Grafoscopio'
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
GrafoscopioGUI >> tree [
|
|
| notebook |
|
|
notebook := GrafoscopioNode new becomeDefaultTestTree.
|
|
tree := TreeModel new.
|
|
tree
|
|
roots: notebook children;
|
|
childrenBlock: [:node | node children];
|
|
displayBlock: [:node | node title ].
|
|
tree whenHighlightedItemChanged:
|
|
[tree selectedItem notNil
|
|
ifTrue: [
|
|
self updateHeader.
|
|
self updateBody.
|
|
]
|
|
].
|
|
^ tree
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
GrafoscopioGUI >> tree: anObject [
|
|
tree := anObject
|
|
]
|
|
|
|
{ #category : #update }
|
|
GrafoscopioGUI >> updateBody [
|
|
"update the displayed content associated to the body of a node"
|
|
|
|
(tree selectedItem content tags = 'código')
|
|
ifTrue: [
|
|
^ nodeBody text: 'I should be playground because I am tagged as ', tree selectedItem content tags
|
|
]
|
|
ifFalse: [
|
|
"nodeBody := self newText."
|
|
^ nodeBody text: tree selectedItem content body
|
|
]
|
|
|
|
|
|
]
|
|
|
|
{ #category : #update }
|
|
GrafoscopioGUI >> updateHeader [
|
|
"update the displayed text associated to the header of a node"
|
|
|
|
^ nodeHeader text: tree selectedItem content header.
|
|
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
GrafoscopioGUI >> windowMainMenu [
|
|
windowMainMenu := MenuModel new
|
|
addGroup: [ :group |
|
|
group addItem: [ :item |
|
|
item
|
|
name: 'Cuaderno';
|
|
icon: Smalltalk ui icons smallObjectsIcon;
|
|
subMenu: self notebookSubMenu ].
|
|
group addItem: [ :item |
|
|
item
|
|
name: 'Proyecto';
|
|
icon: Smalltalk ui icons catalogIcon;
|
|
subMenu: self proyectSubMenu ] ];
|
|
addGroup: [ :group |
|
|
group addItem: [ :item |
|
|
item
|
|
name: nil;
|
|
description: 'Guardar documento';
|
|
icon: Smalltalk ui icons smallSaveIcon;
|
|
action: [ self inform: 'Por implementar...' ] ].
|
|
group addItem: [ :item |
|
|
item
|
|
name: nil;
|
|
description: 'Deshacer';
|
|
icon: Smalltalk ui icons smallUndoIcon;
|
|
action: [ self inform: 'Por implementar...' ] ].
|
|
group addItem: [ :item |
|
|
item
|
|
name: nil;
|
|
description: 'Rehacer';
|
|
icon: Smalltalk ui icons smallRedoIcon;
|
|
action: [ self inform: 'Por implementar...' ] ]];
|
|
addGroup: [ :group |
|
|
group addItem: [ :item |
|
|
item
|
|
name: nil;
|
|
description: 'Agregar nodo';
|
|
icon: MendaIcons new plusIcon;
|
|
action: [ self inform: 'Por implementar...' ] ].
|
|
group addItem: [ :item |
|
|
item
|
|
name: nil;
|
|
description: 'Eliminar nodo';
|
|
icon: MendaIcons new minusIcon;
|
|
action: [ self inform: 'Por implementar...' ] ].
|
|
group addItem: [ :item |
|
|
item
|
|
name: nil;
|
|
description: 'Subir nodo';
|
|
icon: MendaIcons new arrowUpIcon;
|
|
action: [ self inform: 'Por implementar...' ] ].
|
|
group addItem: [ :item |
|
|
item
|
|
name: nil;
|
|
description: 'Bajar nodo';
|
|
icon: MendaIcons new arrowDownIcon;
|
|
action: [ self inform: 'Por implementar...' ] ].
|
|
group addItem: [ :item |
|
|
item
|
|
name: nil;
|
|
description: 'Mover nodo a la izquierda';
|
|
icon: MendaIcons new arrowLeftIcon;
|
|
action: [ self inform: 'Por implementar...' ] ].
|
|
group addItem: [ :item |
|
|
item
|
|
name: nil;
|
|
description: 'Mover nodo a la derecha';
|
|
icon: MendaIcons new arrowRightIcon;
|
|
action: [ self inform: 'Por implementar...' ] ]];
|
|
addGroup: [ :group |
|
|
group addItem: [ :item |
|
|
item
|
|
name: nil;
|
|
description: 'Intercambiar: código <--> texto';
|
|
icon: MendaIcons new smalltalkCodeIcon;
|
|
action: [ self inform: 'Por implementar...' ] ].
|
|
group addItem: [ :item |
|
|
item
|
|
name: nil;
|
|
description: 'Etiquetar como...';
|
|
icon: MendaIcons new tagAddIcon;
|
|
action: [ self inform: 'Por implementar...' ] ].
|
|
group addItem: [ :item |
|
|
item
|
|
name: nil;
|
|
description: 'Desetiquetar ....';
|
|
icon: MendaIcons new tagMinusIcon;
|
|
action: [ self inform: 'Por implementar...' ] ].
|
|
group addItem: [ :item |
|
|
item
|
|
name: nil;
|
|
description: 'Editar etiquetas...';
|
|
icon: FontAwesomeIcons new tagsIcon;
|
|
action: [ self inform: 'Por implementar...' ] ]. ].
|
|
^ windowMainMenu
|
|
]
|
|
|
|
{ #category : #accessing }
|
|
GrafoscopioGUI >> windowMainMenu: anObject [
|
|
windowMainMenu := anObject
|
|
]
|