Grafoscopio/repository/Grafoscopio/GrafoscopioGUI.class.st

638 lines
18 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'
],
#classVars : [
'dockingBar'
],
#classInstVars : [
'dockingBar'
],
#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 : #accessing }
GrafoscopioGUI class >> dockingBar [
^ dockingBar
]
{ #category : #accessing }
GrafoscopioGUI class >> dockingBar: anObject [
dockingBar := anObject
]
{ #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 : #'as yet unclassified' }
GrafoscopioGUI class >> initialize [
self startDockingBar.
]
{ #category : #'graphical interface' }
GrafoscopioGUI class >> startDockingBar [
"Creates a custom docking bar for grafoscopio on top, with shorcuts for most used actions, and a fixed place for asking for help.
Some of the functionalities implemented now in the grafoscopio interface for document trees should be moved here, like the ones
related with help, external tools and grafoscopio updates and about"
| launchMenu helpMenu updateMenu |
launchMenu := MenuMorph new.
launchMenu
add: 'New notebook' target: GrafoscopioNotebook selector: #new;
add: 'Notebook from file...' target: (GrafoscopioNotebook new) selector: #openFromFileSelector;
add: 'Notebook from Internet...' target: (GrafoscopioNotebook new) selector: #openFromUrlUI;
add: 'Recent notebooks...' target: self selector: #openFromRecentlyUsed;
add: 'Example notebooks...' target: self selector: #messageNotImplementedYet;
add: 'Roassal visualizations gallery' target: (RTExampleBrowser new) selector: #open;
add: 'Playground' target: (Smalltalk tools) selector: #openWorkspace;
add: 'Transcript' target: (Smalltalk tools) selector: #openTranscript.
updateMenu := MenuMorph new.
updateMenu
add: 'Grafoscopio' target: self selector: #updateGrafoscopioUI;
add: 'Documentation' target: self selector: #updateDocumentationUI;
add: 'DataViz package' target: self selector: #updateDatavizUI;
add: 'Graphical Interface' target: self selector: #updateUI;
add: 'Database engine' target: ExternalApp selector: #installSQLite32BitsUI;
add: 'Pandoc path' target: ExternalApp selector: #configurePandoc;
add: 'Fossil path' target: ExternalApp selector: #configureFossil;
add: 'All the system' target: self selector: #updateSystem.
helpMenu := MenuMorph new.
helpMenu
add: 'Tutorial in Grafoscopio' target: (self new) selector: #openTutorialInGrafoscopio;
add: 'PDF Manual' target: self selector: #openHelpInPdf;
add: 'HTML Manual' target: self selector: #openHelpInHtml;
add: 'Manual in grafoscopio' target: (self new) selector: #openHelpInGrafoscopio;
add: 'About Grafoscopio' target: self selector: #messageAbout.
dockingBar := DockingBarMorph new.
dockingBar
add: 'Launch' subMenu: launchMenu;
add: 'Update' subMenu: updateMenu;
add: 'Help' subMenu: helpMenu.
dockingBar
adhereToTop;
openInWorld.
]
{ #category : #'graphical interface' }
GrafoscopioGUI class >> updateUI [
"I update the User Interface (UI) with new versions of the docking bar or logos where available.
I'm helpful while testing new functionality that should be expossed to the user via the UI"
self dockingBar
ifNil: [^ self ]
ifNotNil: [
self dockingBar delete.
self startDockingBar]
]
{ #category : #initialization }
GrafoscopioGUI >> initializePresenter [
tree.
nodeHeader acceptBlock: [ :text|
tree selectedItem
ifNotNil: [:x |
x content: text.
self updateTree
]
]
]
{ #category : #initialization }
GrafoscopioGUI >> initializePresenter2 [
tree whenSelectedItemChanged: [:node |
node tag = 'código'
ifTrue: [ ]
ifFalse: [ ]
].
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 >> updateBody2 [
"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
]