From 266d5378a1db5b4d2b5ed72c7516ba816f0e78fb Mon Sep 17 00:00:00 2001 From: Offray Luna Date: Wed, 24 Feb 2016 11:03:53 +0000 Subject: [PATCH] Dataviz as a codependency instead of prerrequisite. --- repository/Grafoscopio/DynamicDict.class.st | 132 ++++++++++++ .../Grafoscopio/GrafoscopioBrowser.class.st | 95 ++++++--- .../Grafoscopio/GrafoscopioGUI.class.st | 197 ++++++++++++++++-- .../Grafoscopio/GrafoscopioNode.class.st | 17 +- 4 files changed, 387 insertions(+), 54 deletions(-) create mode 100644 repository/Grafoscopio/DynamicDict.class.st diff --git a/repository/Grafoscopio/DynamicDict.class.st b/repository/Grafoscopio/DynamicDict.class.st new file mode 100644 index 0000000..6029d30 --- /dev/null +++ b/repository/Grafoscopio/DynamicDict.class.st @@ -0,0 +1,132 @@ +" +I'm just a way to explore Spec and its documentation for learning purposes. +" +Class { + #name : #DynamicDict, + #superclass : #ComposableModel, + #instVars : [ + 'data', + 'list', + 'content' + ], + #category : #'Grafoscopio-UI' +} + +{ #category : #'as yet unclassified' } +DynamicDict class >> defaultSpec [ + + + ^ SpecLayout composed + newRow: [:row | + row + add: #list right: 0.7; + add: #content left: 0.3]; + yourself +] + +{ #category : #accessing } +DynamicDict >> content [ + ^ content +] + +{ #category : #accessing } +DynamicDict >> content: anObject [ + content := anObject +] + +{ #category : #accessing } +DynamicDict >> data [ + data := {'first' -> 'I am just text' . 'second' -> 'ProfStef openPharoZenWorkspace' } asOrderedDictionary. + ^ data +] + +{ #category : #'as yet unclassified' } +DynamicDict >> initializePresenter [ + list whenSelectedItemChanged: [:item | + item = 'first' + ifTrue: [ self rebuildWithTextLayoutFor: item ]. + item = 'second' + ifTrue: [ self rebuildWithCodeLayoutFor: item ]. + ] +] + +{ #category : #initialization } +DynamicDict >> initializeWidgets [ + + + list := self newList. + list items: self data keys. + content := self newText. + self focusOrder + add: list; + add: content. +] + +{ #category : #accessing } +DynamicDict >> list [ + ^ list +] + +{ #category : #accessing } +DynamicDict >> list: anObject [ + list := anObject +] + +{ #category : #'as yet unclassified' } +DynamicDict >> rebuildWithCodeLayoutFor: key [ + | newLayout | + + content := GlamourPresentationModel new. + content presentationClass: GTPlayground startOn: (GTPlayPage new saveContent: (data at: key)). + newLayout := SpecLayout composed + newRow: [:row | + row + add: #list right: 0.7; + add: #content left: 0.3]; + yourself. + self needRebuild: false. + content needRebuild: true. + Transcript show: 'código + ', self content asString, String cr. + self buildWithSpecLayout: newLayout. +] + +{ #category : #'as yet unclassified' } +DynamicDict >> rebuildWithTextLayout [ + | newLayout | + + content := self newText. + newLayout := SpecLayout composed + newRow: [:row | + row + add: #list right: 0.7; + add: #content left: 0.3]; + yourself. + self needRebuild: false. + list needRebuild: false. + content needRebuild: true. + Transcript show: 'texto + ', self content asString, String cr.. + self buildWithSpecLayout: newLayout. +] + +{ #category : #'as yet unclassified' } +DynamicDict >> rebuildWithTextLayoutFor: key [ + | newLayout | + + content := self newText text: (data at: key). + newLayout := SpecLayout composed + newRow: [:row | + row + add: #list right: 0.7; + add: #content left: 0.3]; + yourself. + self needRebuild: false. + list needRebuild: false. + content needRebuild: true. + Transcript show: 'texto + ', self content asString, String cr.. + self buildWithSpecLayout: newLayout. +] + +{ #category : #api } +DynamicDict >> title [ + ^'Dynamic UI | test' +] diff --git a/repository/Grafoscopio/GrafoscopioBrowser.class.st b/repository/Grafoscopio/GrafoscopioBrowser.class.st index 2dcf1a0..7d3e9c6 100644 --- a/repository/Grafoscopio/GrafoscopioBrowser.class.st +++ b/repository/Grafoscopio/GrafoscopioBrowser.class.st @@ -35,7 +35,7 @@ Class { #category : #'Grafoscopio-UI' } -{ #category : #'as yet unclassified' } +{ #category : #configuration } GrafoscopioBrowser class >> configureFossil [ "Stablish where is located fossil according to the operative system and the input of the user" | fileStream | @@ -46,7 +46,7 @@ GrafoscopioBrowser class >> configureFossil [ fossil := fileStream name asFileReference fullName. ] -{ #category : #'as yet unclassified' } +{ #category : #configuration } GrafoscopioBrowser class >> configurePandoc [ "Stablish where is located pandoc according to the operative system and/or the input of the user" | fileStream | @@ -61,7 +61,7 @@ GrafoscopioBrowser class >> configurePandoc [ ] -{ #category : #'as yet unclassified' } +{ #category : #configuration } GrafoscopioBrowser class >> configureSettings [ "Stablish several 'global' settings according to to image location and the operative system. For the moment we're gonna use hardcoded paths, but in the future this will be a smarter method finding the proper external tool and setting up it." @@ -84,23 +84,40 @@ GrafoscopioBrowser class >> configureSettings [ ] ] -{ #category : #'as yet unclassified' } +{ #category : #'graphical interface' } GrafoscopioBrowser class >> messageAbout [ "Shows the author, license, sponsors and main contributors to the project and point to further documentation on the web" UIManager default alert: - 'Grafosocpio', + '_.:| Grafoscopio |:._', (String with: Character cr), - '(c) Copyright 2014 by Offray Vladimir Luna Cárdenas', + '(c) Copyright 2014-2016 by Offray Vladimir Luna Cárdenas', (String with: Character cr), 'Covered under MIT license.', (String with: Character cr), (String with: Character cr), - 'SPONSORS:', + '[ Sponsors ]', (String with: Character cr), 'mutabiT | www.mutabit.com ', (String with: Character cr), - 'Fundación Universitaria Los Libertadores | www.ulibertadores.edu.co ', + 'HiTec Lab, Fundación Universitaria Los Libertadores | www.ulibertadores.edu.co ', + (String with: Character cr), + (String with: Character cr), + '[ Thanks to ]', + (String with: Character cr), + 'HackBo, Hackerspace Bogota | http://hackbo.co', + (String with: Character cr), + '// Regular workshops attendees \\ + Rafael Medida, Iván Pulido, Camilo Hurtado', + (String with: Character cr), + '// Coffe talk (mostly about grafoscopio) \\ + Yanneth Gil, Andrés Calderón, Luis Alejandro Bernal', + (String with: Character cr), + '// Pharo, Moose and Agile Visualization communities \\ + Tudor Girba, Alexandre Bergel, Nicolai Hess, Peter Uhnák, Milton Mamani ', + (String with: Character cr), + '// Family support while writing, coding & travelling (among others!) \\ + Divian Luna, Hilda Cárdenas', (String with: Character cr), (String with: Character cr), 'For further details and versions go to:', @@ -111,7 +128,7 @@ GrafoscopioBrowser class >> messageAbout [ title: 'About Grafoscopio'. ] -{ #category : #'as yet unclassified' } +{ #category : #'graphical interface' } GrafoscopioBrowser class >> messageNoRecentDocuments [ "Shows that a feature is not implemeted and point to further documentation on the web" @@ -127,7 +144,7 @@ GrafoscopioBrowser class >> messageNoRecentDocuments [ title: 'No hay documentos recientes'. ] -{ #category : #'as yet unclassified' } +{ #category : #'graphical interface' } GrafoscopioBrowser class >> messageNotImplementedYet [ "Shows that a feature is not implemeted and point to further documentation on the web" @@ -143,12 +160,12 @@ GrafoscopioBrowser class >> messageNotImplementedYet [ title: 'No implementado aún'. ] -{ #category : #'as yet unclassified' } +{ #category : #'graphical interface' } GrafoscopioBrowser class >> open [ ^ self new open ] -{ #category : #'as yet unclassified' } +{ #category : #'graphical interface' } GrafoscopioBrowser class >> openFromRecentlyUsed [ "Tags the node passed as argument with a value from the collection of tags available" | selection | @@ -203,7 +220,7 @@ GrafoscopioBrowser class >> showSettings [ Transcript show: pandoc ] -{ #category : #'as yet unclassified' } +{ #category : #'graphical interface' } GrafoscopioBrowser 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 @@ -225,6 +242,7 @@ GrafoscopioBrowser class >> startDockingBar [ updateMenu := MenuMorph new. updateMenu add: 'Grafoscopio' target: GrafoscopioBrowser selector: #updateGrafoscopio; + add: 'Galeria de proyectos' target: GrafoscopioBrowser selector: #updateDataviz add: 'Prerrequisitos' target: GrafoscopioBrowser selector: #updatePrerrequisites; add: 'Documentación > Tutorial' target: GrafoscopioBrowser selector: #updateDocumentationTemp; add: 'Documentación > Toda' target: GrafoscopioBrowser selector: #updateDocumentation; @@ -252,7 +270,28 @@ GrafoscopioBrowser class >> startDockingBar [ openInWorld. ] -{ #category : #'as yet unclassified' } +{ #category : #updating } +GrafoscopioBrowser class >> updateDataviz [ + "Updates Dataviz package with new versions of itself take from the source code repository and + the User Interface" + | update | + + update := (UIManager default + question: '¿Desea actualizar la galería de proyectos' + title: 'Actualizar galeria de proyectos'). + update ifNotNil: [ + update + ifTrue: [ + "Data visualization helpers" + Gofer new + smalltalkhubUser: 'Offray' project: 'Dataviz'; + package: 'Dataviz'; + load. + self inform: 'Actualización de galeria de proyectos terminada'] + ifFalse: [self inform: 'Actualización de grafoscopio no realizada']] +] + +{ #category : #updating } GrafoscopioBrowser class >> updateDocumentation [ "Updates documentation (manual, tutorials) from official repository" @@ -289,7 +328,7 @@ GrafoscopioBrowser class >> updateDocumentation [ ]. ] -{ #category : #'as yet unclassified' } +{ #category : #updating } GrafoscopioBrowser class >> updateDocumentationOld [ | localRepository remoteRepository | @@ -313,7 +352,7 @@ localRepository exists ] ] -{ #category : #'as yet unclassified' } +{ #category : #updating } GrafoscopioBrowser class >> updateDocumentationTemp [ "Updates documentation (manual, tutorials) from official repository" @@ -346,7 +385,7 @@ GrafoscopioBrowser class >> updateDocumentationTemp [ ]. ] -{ #category : #'as yet unclassified' } +{ #category : #updating } GrafoscopioBrowser class >> updateGrafoscopio [ "Updates Grafoscopio with new versions of itself take from the source code repository and the User Interface" @@ -363,7 +402,7 @@ GrafoscopioBrowser class >> updateGrafoscopio [ ifFalse: [self inform: 'Actualización de grafoscopio no realizada']] ] -{ #category : #'as yet unclassified' } +{ #category : #updating } GrafoscopioBrowser class >> updateGrafoscopioScript [ "Updates Grafoscopio with new versions of itself take from the source code repository and the User Interface" @@ -374,7 +413,7 @@ GrafoscopioBrowser class >> updateGrafoscopioScript [ self updateUI. ] -{ #category : #'as yet unclassified' } +{ #category : #updating } GrafoscopioBrowser class >> updatePrerrequisites [ "Updates the system prerequisites with new versions of itself take from the source code repository" | update | @@ -392,7 +431,7 @@ GrafoscopioBrowser class >> updatePrerrequisites [ ] ] -{ #category : #'as yet unclassified' } +{ #category : #updating } GrafoscopioBrowser class >> updatePrerrequisitesScript [ "Updates the system prerequisites with new versions of itself take from the source code repository" @@ -400,7 +439,7 @@ GrafoscopioBrowser class >> updatePrerrequisitesScript [ Gofer it smalltalkhubUser: 'ObjectProfile' project: 'Roassal2'; configurationOf: 'Roassal2'; - loadVersion: '1.15'. + loadDevelopment. "Support for the STON format used in file persistance for grafoscopio notebooks" Gofer new @@ -448,12 +487,6 @@ GrafoscopioBrowser class >> updatePrerrequisitesScript [ url: 'http://smalltalkhub.com/mc/PharoExtras/NBSQLite3/main'; package: 'NBSQLite3-Examples'; load. - - "Data visualization helpers" - Gofer new - smalltalkhubUser: 'Offray' project: 'Dataviz'; - package: 'Dataviz'; - load. "Support for Operative System integration" Gofer new @@ -474,7 +507,7 @@ GrafoscopioBrowser class >> updatePrerrequisitesScript [ ] -{ #category : #'as yet unclassified' } +{ #category : #updating } GrafoscopioBrowser class >> updateSystem [ "Updates the system with new versions of itself take from the source code repository" | update | @@ -495,7 +528,7 @@ GrafoscopioBrowser class >> updateSystem [ ] -{ #category : #'as yet unclassified' } +{ #category : #updating } GrafoscopioBrowser class >> updateUI [ "Updates the User Interface (UI) with new versions of the docking bar or logos where available. Helpful while testing new functionality that should be expossed to the user via the UI" @@ -622,8 +655,8 @@ GrafoscopioBrowser >> bodyIn: constructor [ { #category : #'graphical interface' } GrafoscopioBrowser >> bodyIn: constructor for: aNode [ - "Shows the body in a constructor for selected node, if node is not tagged. If it is tagged it will return itself, so it can be rendered - properly for other messages" + "Shows the body in a constructor for selected node, if node is not tagged. + If it is tagged it will return itself, so it can be rendered properly for other messages" | specialTags | diff --git a/repository/Grafoscopio/GrafoscopioGUI.class.st b/repository/Grafoscopio/GrafoscopioGUI.class.st index c3bcb22..b8c8519 100644 --- a/repository/Grafoscopio/GrafoscopioGUI.class.st +++ b/repository/Grafoscopio/GrafoscopioGUI.class.st @@ -8,12 +8,12 @@ My main responsability is to provide grafoscopio with graphical widgets and othe " Class { #name : #GrafoscopioGUI, - #superclass : #ComposableModel, + #superclass : #DynamicComposableModel, #instVars : [ 'windowMainMenu', 'tree', 'nodeHeader', - 'nodeDetails', + 'nodeBody', 'headerRefreshProcess', 'selected' ], @@ -40,12 +40,158 @@ GrafoscopioGUI class >> defaultSpec [ ] right: 0.7; addSplitter; newColumn: [ :nodePart | - nodePart add: #nodeDetails] left: 0.3. + 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 @@ -57,8 +203,9 @@ GrafoscopioGUI class >> exampleBootstrapUI [ ui title: 'new | Grafoscopio'. ui instantiateModels: #( tree TreeModel - header TextModel - play GlamourPresentationModel). + header TextInputFieldModel + bodyWhenMarkup TextModel + bodyWhenCode GlamourPresentationModel). notebook := GrafoscopioNode new becomeDefaultTestTree. ui tree roots: notebook children; @@ -74,7 +221,7 @@ GrafoscopioGUI class >> exampleBootstrapUI [ addHSplitter; newRow: #header bottom: 0.8] right: 0.7; addVSplitter; - newColumn: #play]; + newColumn: #bodyWhenCode]; yourself. ui openWithSpecLayout: lay. @@ -100,23 +247,26 @@ GrafoscopioGUI >> initializeWidgets [ windowMainMenu := self windowMainMenu. tree := self tree. nodeHeader := self newTextInput. - nodeDetails := self newText. + nodeBody := + tree selectedItem + ifNotNil: [ self updateBody ] + ifNil: [nodeBody := self newText]. windowMainMenu applyTo: self. self focusOrder add: windowMainMenu; add: tree; add: nodeHeader; - add: nodeDetails. + add: nodeBody. ] { #category : #accessing } -GrafoscopioGUI >> nodeDetails [ - ^ nodeDetails +GrafoscopioGUI >> nodeBody [ + ^ nodeBody ] { #category : #accessing } -GrafoscopioGUI >> nodeDetails: anObject [ - nodeDetails := anObject +GrafoscopioGUI >> nodeBody: anObject [ + nodeBody := anObject ] { #category : #accessing } @@ -233,8 +383,9 @@ GrafoscopioGUI >> tree [ tree whenHighlightedItemChanged: [tree selectedItem notNil ifTrue: [ - Transcript show: tree selectedItem content header, String cr. - self updateHeader] + self updateHeader. + self updateBody. + ] ]. ^ tree ] @@ -244,9 +395,25 @@ 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" + "update the displayed text associated to the header of a node" ^ nodeHeader text: tree selectedItem content header. diff --git a/repository/Grafoscopio/GrafoscopioNode.class.st b/repository/Grafoscopio/GrafoscopioNode.class.st index 3406ce3..e0d63b7 100644 --- a/repository/Grafoscopio/GrafoscopioNode.class.st +++ b/repository/Grafoscopio/GrafoscopioNode.class.st @@ -146,18 +146,19 @@ GrafoscopioNode >> asSton [ { #category : #initialization } GrafoscopioNode >> becomeDefaultTestTree [ - | node1 node2 node3 | + | node1 node2 node3 | self level: 0. self header: 'Arbol principal'. - node1 := GrafoscopioNode - header: 'Nodo 1' + node1 := GrafoscopioNode new + header: 'Nodo 1'; body: 'Texto 1'. - node2 := GrafoscopioNode - header: 'Nodo 2' + node2 := GrafoscopioNode new + header: 'Nodo 2'; body: 'Texto 2'. - node3 := GrafoscopioNode - header: 'Nodo 3' - body: 'Texto 3'. + node3 := GrafoscopioNode new + header: 'Nodo 3'; + body: 'ProfStef openPharoZenWorkspace'; + tagAs: 'código'. self addNode: node1; addNode: node2.