From f251c554643922cdb004875af9b63db836a0c46a Mon Sep 17 00:00:00 2001 From: Offray Luna Date: Sat, 5 Aug 2017 17:00:38 +0000 Subject: [PATCH] Implementing tags in nodes. --- .../Grafoscopio/GrafoscopioBrowser.class.st | 642 ------------------ .../Grafoscopio/GrafoscopioNode.class.st | 76 ++- .../Grafoscopio/GrafoscopioNotebook.class.st | 304 +++++---- 3 files changed, 217 insertions(+), 805 deletions(-) delete mode 100644 repository/Grafoscopio/GrafoscopioBrowser.class.st diff --git a/repository/Grafoscopio/GrafoscopioBrowser.class.st b/repository/Grafoscopio/GrafoscopioBrowser.class.st deleted file mode 100644 index d4e0b3c..0000000 --- a/repository/Grafoscopio/GrafoscopioBrowser.class.st +++ /dev/null @@ -1,642 +0,0 @@ -" -I am a graphical interface for showing trees, outlines and grafoscopio notebooks. - -Instance Variables - browser: - -browser - - xxxxx - -" -Class { - #name : #GrafoscopioBrowser, - #superclass : #Object, - #instVars : [ - 'browser', - 'mainTree', - 'tagsAvailable', - 'cacheNode', - 'workingFile' - ], - #classVars : [ - 'dockingBar', - 'draftsLocation', - 'recentTrees' - ], - #classInstVars : [ - 'workingFile' - ], - #category : #'Grafoscopio-UI' -} - -{ #category : #tags } -GrafoscopioBrowser >> addTagTo: aNode [ - "Tags the node passed as argument with a value from the collection of tags available" - | selection | - - tagsAvailable isNil - ifFalse: [ - selection := UIManager default chooseFrom: tagsAvailable title: 'Choose a tag'. - aNode tagAs: (tagsAvailable at: selection) - ] - ifTrue: [self messageNoTagsAvailable]. - browser update. - -] - -{ #category : #tags } -GrafoscopioBrowser >> addToTagsAvailable [ - "Adds a tag to the collection of tags available" - - | tag | - tagsAvailable isNil - ifTrue: [tagsAvailable := OrderedCollection new]. - tag := UIManager default - textEntry: 'Nombre de la etiqueta' - title: 'Agregue una etiqueta'. - tagsAvailable add: tag. - -] - -{ #category : #'graphical interface' } -GrafoscopioBrowser >> bodyForCodeIn: constructor for: aNode [ - "Shows the body of a node as an interactive playground. If node is not tagged it will return itself, - so it can be rendered properly for other messages" - - | innerBrowser | - - aNode tags = 'código' - ifFalse: [^self]. - - innerBrowser := GTPlayground new. - constructor custom: innerBrowser. - -] - -{ #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" - - | specialTags | - - specialTags := #('código'). - (specialTags includes: aNode tags) - ifTrue: [^self]. - (constructor text) - title: 'Texto '; - format:[ - aNode body isNil - ifTrue: [ '' ] - ifFalse: [ aNode body]]. -] - -{ #category : #'graphical interface' } -GrafoscopioBrowser >> buildBrowserNamed: aName [ -"Main method for building the interface for trees and its nodes. -The name of the browser corresponds to the name of the file -where tree is stored (or is named 'draft.ston' by default)" - -self configureInitialTags. - -browser := GLMTabulator new - title: aName, ' | Grafoscopio'. - -browser - column: [:c | - c row: #tree span: 6; - row: #nodeHeader span: 1] span: 2; - column: [ :c | - c row: #nodeBody span: 2] span: 5. -browser - updateOn: GLMItemAdded from: #yourself; - updateOn: GLMItemRemoved from: #yourself. - -(browser transmit) - to: #tree; - andShow: [:a | self treeOn: a]. -"Creating a self updatable body pane" -(browser transmit) - from: #tree port: #selection; - to: #nodeBody; - when: [:selection | selection notNil]; - andShow: [ :a :node | - self bodyIn: a for: node. - self bodyForCodeIn: a for: node ]. -(browser transmit ) - from: #tree port: #selection; - from: #nodeBody port: #text; - when: [:node :text | text notNil & node notNil]; - to: #nodeBody port: #neverland; - transformed: [:node :content | - node body: content asString. - "node tags = 'código' - ifFalse: [node body: content asString] - ifTrue: [node body: content asString. Transcript show: content asString]"]. -(browser transmit) - from: #tree; - to: #nodeHeader; - andShow: [ :h | self headerOn: h ]. -(browser transmit ) - from: #tree port: #selection; - from: #nodeHeader port: #text; - to: #nodeHeader port: #neverland1; - when: [:node :text | text notNil & node notNil]; - transformed: [:node :text | node header: text asString] -] - -{ #category : #'system-support' } -GrafoscopioBrowser >> configureInitialTags [ - "Configures a list of predefined tags available to use. More tags should be added from a repository. - The idea is that nodes are processed and show differently according to their tags. So users should be - able to define their own tags with custom UI and behaviour" - - tagsAvailable := OrderedCollection new. - tagsAvailable - add: 'código'; - add: 'ejercicio'; - add: 'invisible'; - add: 'obra'; - add: 'original'; - add: 'transmediado'. -] - -{ #category : #persistence } -GrafoscopioBrowser >> copyNodeIntoCache: aNode [ - "Copy the contents of the current node into cacheNode. It doesn't work recursively yet, so it doen't copy the children of the nodes" - - cacheNode := GrafoscopioNode new. - cacheNode header: (aNode header). - cacheNode body: (aNode body). - self inform: 'Nodo copiado: ', aNode header -] - -{ #category : #bibliography } -GrafoscopioBrowser >> customKeys [ - "Replaces the default key in a BibTeX file for a custom key taken from the 'shorttitle' field. - Useful when autogenerated BibTeX has cryptic or non easy to memorize keys (for example in some - Zotero exports)" - | bibFile bibliography bibStream bibOutputer | - bibFile := ((workingFile parent) children - detect: [:each | each basename endsWith: 'bib' ] ifNone: [ ]). - bibFile ifNotNil: [ - bibliography := CZBibParser parse: bibFile contents. - bibStream := '' writeStream. - (bibliography entries) do: [:bibItem | - bibItem fields do: [:some | some key = 'shorttitle' - ifTrue: [ bibItem key: some value ]]. - bibOutputer := CZBibtexOutputer new. - bibStream nextPutAll: - (bibOutputer entryToBibtexString: bibItem); cr]. - bibFile writeStreamDo: [:stream | - stream nextPutAll: bibStream contents withUnixLineEndings ]]. -] - -{ #category : #persistence } -GrafoscopioBrowser >> exportAsHtml [ - "I exports the current tree to HTML, using the same name but different extension (.html). - IMPORTANT: Pandoc must be installed in your system. In the future Grafoscopio will provide" - | markdownFileLocation htmlFileLocation | - markdownFileLocation := ((workingFile parent) / workingFile basenameWithoutExtension) fullName, '.markdown'. - htmlFileLocation := ((workingFile parent) / workingFile basenameWithoutExtension) fullName, '.html'. - ExternalApp pandoc notNil - ifTrue:[ - (Smalltalk platform name = 'unix') | (Smalltalk platform name = 'Mac OS') - ifTrue: [ - OSProcess command: 'pandoc ', ' ', markdownFileLocation , ' --standalone -o ' , htmlFileLocation. - OSProcess command: 'exec echo "exportando como html"'. - self inform: 'Archivo exportado como html en: ', htmlFileLocation]. - Smalltalk platform name = 'Win32' - ifTrue: [ OSProcess command: 'pandoc ', markdownFileLocation , ' --standalone -o ' , htmlFileLocation ]] - ifFalse: [ExternalApp pandoc]. -] - -{ #category : #persistence } -GrafoscopioBrowser >> exportAsLatex [ - "I Export the current tree to LaTeX, using the same name but different extension (.tex). - IMPORTANT: The user needs to have TeX installed with minted support and pygments for syntax highlighting. - More details at: http://ctan.dcc.uchile.cl/macros/latex/contrib/minted/minted.pdf" - | markdownFileLocation latexFileLocation fileName | - fileName := workingFile basenameWithoutExtension. - markdownFileLocation := ((workingFile parent) / fileName) fullName, '.markdown'. - latexFileLocation := ((workingFile parent) / fileName) fullName, '.tex'. - ExternalApp pandoc binaryLocation exists - ifFalse: [ExternalApp configurePandoc] - ifTrue:[ - OSProcess command: - 'pandoc ', markdownFileLocation, - ' -V documentclass:article -V geometry:margin=2cm --standalone -o ' , - fileName, '.tex'. - "Moving the pdf output to the expected location" - latexFileLocation asFileReference exists ifTrue: [latexFileLocation asFileReference ensureDelete ]. - (FileLocator imageDirectory parent / (fileName, '.tex')) - moveTo: latexFileLocation asFileReference. - "Cleaning left overs" - (FileLocator imageDirectory parent / (fileName, '.tex')) ensureDelete. - self inform: 'Archivo exportado como latex en: ', latexFileLocation - ] -] - -{ #category : #persistence } -GrafoscopioBrowser >> exportAsPdf [ - "Exports the current tree to HTML, using the same name but different extension (.pdf). - IMPORTANT: The user needs to have installed TeX to create the pdf." - | latexFileLocation pdfFileLocation fileName | - fileName := workingFile basenameWithoutExtension. - self exportAsLatex. - latexFileLocation := ((workingFile parent) / fileName) fullName, '.tex'. - pdfFileLocation := ((workingFile parent) / fileName) fullName, '.pdf'. - '/usr/bin/xelatex' asFileReference exists - ifTrue: [ - "Generating the pdf" - OSProcess command: 'xelatex --shell-escape ', latexFileLocation. - "Moving the pdf output to the expected location" - pdfFileLocation asFileReference exists ifTrue: [pdfFileLocation asFileReference ensureDelete ]. - (FileLocator imageDirectory parent / (fileName, '.pdf')) - moveTo: pdfFileLocation asFileReference. - "Cleaning left overs" - #('.aux' '.out' '.log') do: [ :fileExension | - (FileLocator imageDirectory parent asFileReference / (fileName, fileExension)) ensureDelete]. - (FileLocator imageDirectory parent asFileReference / ('_minted-', fileName)) deleteAll. - self inform: 'Archivo exportado como pdf en: ', pdfFileLocation] - ifFalse: [ - self inform: - 'Necesita instalar XeLaTeX/TeX más información en:', String cr,' - http://xetex.sourceforge.net/' ]. -] - -{ #category : #'graphical interface' } -GrafoscopioBrowser >> headerOn: constructor [ - "Shows the body of a selected node" - - (constructor text) - title: 'Cabecera '; - format:[:eachNode | - (eachNode header) isNil - ifTrue: [ '' ] - ifFalse: [ eachNode header]]. -] - -{ #category : #'system-support' } -GrafoscopioBrowser >> installPandoc [ - "Installs pandoc binary for each major platform: Linux, Windows, Mac" - | linuxSupplies | - linuxSupplies := (FileSystem disk workingDirectory - / 'Platform' / 'Linux' / 'Programs' / 'Pandoc') - ensureCreateDirectory. - -] - -{ #category : #'graphical interface' } -GrafoscopioBrowser >> messageNoTagsAvailable [ - "Shows that there is no tags available and the procedure to add some tags" - - UIManager default - abort: - 'Use primero el menu:', - (String with: Character cr), - '"Etiquetas > Agregar a disponibles"', - (String with: Character cr), - 'para agregar etiquetas y luego sí agregue etiquetas al nodo' - title: 'Sin etiquetas disponibles!' -] - -{ #category : #'graphical interface' } -GrafoscopioBrowser >> messageNotImplementedYet [ - "Shows that a feature is not implemeted and point to further documentation on the web" - - UIManager default abort: - 'Esta funcionalidad aún no está implementada!', - (String with: Character cr), - 'Para información sobre futuras versiones, por favor visite: ', - (String with: Character cr), - (String with: Character cr), - 'http://mutabit.com/grafoscopio', - (String with: Character cr), - (String with: Character cr) - title: 'No implementado aún'. -] - -{ #category : #persistence } -GrafoscopioBrowser >> open [ - "Opens a new browser with a default tree and assigns a default draft file for storing it. - This is changed when the file is saved with the 'Save as' menu option" - - "Opens a new browser with a default tree" - "GrafoscopioBrowser configureSettings." - self openDefault. - -] - -{ #category : #persistence } -GrafoscopioBrowser >> openDefault [ - "Opens a new browser with a default tree" - "GrafoscopioBrowser configureSettings." - self buildBrowserNamed: 'draft.ston'. - mainTree := GrafoscopioNode new. - mainTree becomeDefaultTree. - workingFile := draftsLocation / 'draft.ston'. - self saveToFile: workingFile. - self openFromFile: workingFile. -" browser openOn: mainTree children." - -] - -{ #category : #persistence } -GrafoscopioBrowser >> openFromFile: aFileName [ -"Opens a tree from a file named aFileName" - - | currentChildren | - "GrafoscopioBrowser configureSettings." - - workingFile := aFileName. - currentChildren := (STON fromString: aFileName contents). - self buildBrowserNamed: aFileName basenameWithIndicator. - mainTree := GrafoscopioNode new - header: (currentChildren at: 1) parent header; - level: (currentChildren at: 1) parent level; - children: currentChildren. - browser openOn: mainTree children. -] - -{ #category : #persistence } -GrafoscopioBrowser >> openFromFileSelector [ - "Opens a tree from a file by using the file selector GUI." - "REFACTORING NOTES: This sould call openFromFile, instead of having the code repeated here. - This creates errors on debugging and worse on proper behavior" - | fileStream currentChildren | - "GrafoscopioBrowser configureSettings." - fileStream := UIManager default - fileOpen: 'Choose a notebook file' - extensions: #('ston'). - - fileStream isNil ifTrue: [ ^nil ]. - workingFile := fileStream name asFileReference. - currentChildren := (STON fromStream: fileStream). - self buildBrowserNamed: workingFile basenameWithIndicator. - recentTrees isNil - ifTrue:[recentTrees := OrderedCollection new]. - "recentTrees detect: workingFile ifFound: [recentTrees add: workingFile]." - recentTrees add: workingFile. - mainTree := GrafoscopioNode new - header: (currentChildren at: 1) parent header; - level: (currentChildren at: 1) parent level; - children: currentChildren. - browser openOn: mainTree children. -] - -{ #category : #persistence } -GrafoscopioBrowser >> openHelpInGrafoscopio [ -"Opens the help tree from a file" - - | currentChildren | - "GrafoscopioBrowser configureSettings." - workingFile := (FileSystem disk workingDirectory / 'Docs' / 'Es' / 'Manual' / 'manual-grafoscopio.ston') asFileReference. - currentChildren := (STON fromString: workingFile contents). - self buildBrowserNamed: workingFile basenameWithIndicator. - mainTree := GrafoscopioNode new - header: 'Arbol principal'; - level: 0. - mainTree children: currentChildren. - browser openOn: mainTree children. -] - -{ #category : #persistence } -GrafoscopioBrowser >> openTutorialInGrafoscopio [ -"Opens the help tree from a file" - - | currentChildren | - "GrafoscopioBrowser configureSettings." - workingFile := (FileSystem disk workingDirectory / 'Docs' / 'Es' / 'Tutoriales' / 'tutorial.ston') asFileReference. - currentChildren := (STON fromString: workingFile contents). - self buildBrowserNamed: workingFile basenameWithIndicator. - mainTree := GrafoscopioNode new - header: 'Arbol principal'; - level: 0. - mainTree children: currentChildren. - browser openOn: mainTree children. -] - -{ #category : #persistence } -GrafoscopioBrowser >> replaceContentsFromCache: aNode [ - "Replaces the contents of aNode from the ones in cacheNode. It doesn't work recursively yet, so it doen't copy the children of the nodes" - - cacheNode notNil - ifTrue: [ - aNode header: cacheNode header. - aNode body: cacheNode body. - self inform: 'Contenidos reemplazados'] - ifFalse: [self inform: 'El nodo cache está vacio'] -] - -{ #category : #persistence } -GrafoscopioBrowser >> repositoryCommit [ - "Commits current changes to the open repository" - - fossil notNil ifTrue: [ - OSProcess command: - 'cd ', localRepository parent fullName, '; ', - fossil, ' commit -m "" --no-warnings; ', - 'echo "Commited changes to the repository"'. ] - - -] - -{ #category : #persistence } -GrafoscopioBrowser >> repositoryCredentials [ - "Asks for the user credentials of the current project repository" - - repositoryUser := UIManager default request: 'Ingrese su usuario en el repositorio del proyecto'. - repositoryPassword := UIManager default request: 'Ingrese su contraseña en el repositorio del proyecto'. -] - -{ #category : #persistence } -GrafoscopioBrowser >> saveToFile: aFileReference [ - "Saves the current tree/document to a file" - - | file writeStream markdownFile | - - file := aFileReference. - file ifNil: [ self inform: 'Exportación cancelada'. ^ self ]. - - writeStream := file writeStream. - workingFile := writeStream name asFileReference. - markdownFile := (workingFile parent) / (workingFile basenameWithoutExtension, '.markdown'). - markdownFile ensureCreateFile. - [ self exportAsSton: mainTree on: writeStream. - self exportAsMarkdown: mainTree on: markdownFile ] - ensure: [ writeStream ifNotNil: #close ]. - recentTrees isNil - ifTrue:[recentTrees := OrderedCollection new]. - recentTrees add: workingFile. - browser update. -] - -{ #category : #persistence } -GrafoscopioBrowser >> saveToFileUI [ - "Saves the current tree to a file" - - | file | - - file := UIManager default - fileSave: 'Save file as...' - extensions: #('ston') - path: nil. - file - ifNil: [ self inform: 'File export canceled'. ^ self ] - ifNotNil:[self saveToFile: file]. - browser update. -] - -{ #category : #persistence } -GrafoscopioBrowser >> saveWorkingTree [ - "Saves the current tree to the user predefined file location used when he/she opened it." - - | markdownFile | - markdownFile := (workingFile parent) / (workingFile basenameWithoutExtension, '.markdown'). - markdownFile exists ifTrue: [ markdownFile delete ]. - markdownFile ensureCreateFile. - workingFile exists ifTrue: [ workingFile delete ]. - workingFile ensureCreateFile. - [ self exportAsSton: mainTree on: (workingFile writeStream). - self exportAsMarkdown: mainTree on: markdownFile - ] ensure: [ (workingFile writeStream) ifNotNil: #close.]. - self inform: 'Archivo guardado como: ', workingFile asString. -] - -{ #category : #tags } -GrafoscopioBrowser >> showTagsAvailable [ - "Adds a tag to the collection of tags available" - - tagsAvailable isNil - ifTrue: [self messageNoTagsAvailable] - ifFalse: [self messageNotImplementedYet] - -] - -{ #category : #'graphical interface' } -GrafoscopioBrowser >> treeOn: constructor [ - "Shows the correspondent tree of a node" - - (constructor tree) "Layout" - title: mainTree header; - children: [ :eachNode | - (eachNode children) isNil - ifTrue: [ self inform: 'Seleccione un nodo para ver su contenido' ] - ifFalse:[ eachNode children ] ]; - format:[:eachNode | - (eachNode header) isNil - ifTrue: [ '' ] - ifFalse: [ eachNode header ]]; - tags: [:eachNode | - (eachNode tags) isNil - ifFalse: [ (eachNode tags) asSymbol ] - ifTrue: [ #() ] ]; - - "Nodes Toolbar - ==============" - - "Adding nodes" - act: [:treePresentation | - (treePresentation selection) isNotNil - ifTrue: [treePresentation selection addNodeAfterMe]. - treePresentation update] - icon: GLMUIThemeExtraIcons glamorousZoomIn - entitled: 'Adicionar nodo'; - "Removing nodes" - act: [:treePresentation | - (treePresentation selection isNotNil) - ifTrue: [(treePresentation selection parent) - removeNode: treePresentation selection] - ifFalse: [treePresentation entity removeLast]. - treePresentation update] - icon: GLMUIThemeExtraIcons glamorousZoomOut - entitled: 'Remover nodo'; - - "Move nodes in the same hierarchy" - act: [:treePresentation | - (treePresentation selection isNotNil) - ifTrue: [treePresentation selection moveBefore]. - treePresentation update] - icon: GLMUIThemeExtraIcons glamorousUp - entitled: 'Mover nodo hacia arriba'; - - act: [:treePresentation | - (treePresentation selection isNotNil) - ifTrue: [treePresentation selection moveAfter]. - treePresentation update] - icon: GLMUIThemeExtraIcons glamorousDown - entitled: 'Mover nodo hacia abajo'; - - act: [:treePresentation | - (treePresentation selection isNotNil) - ifTrue: [treePresentation selection promote]. - treePresentation update] - icon: GLMUIThemeExtraIcons glamorousLeft - entitled: 'Mover nodo hacia la izquierda'; - - act: [:treePresentation | - (treePresentation selection isNotNil) - ifTrue: [treePresentation selection demote]. - treePresentation update] - icon: GLMUIThemeExtraIcons glamorousRight - entitled: 'Mover nodo hacia la derecha'; - - act: [ :treePresentation | treePresentation update ] - icon: GLMUIThemeExtraIcons glamorousRefresh - entitled: 'Actualizar vista del árbol'; - - act: [self saveWorkingTree] - icon: GLMUIThemeExtraIcons glamorousSave - entitled: 'Guardar árbol'; - - "Options Menu - =============" - - "For trees" - act: [self saveToFileUI] entitled: 'Guardar como ...' categorized: 'Arbol'; - act: [self saveWorkingTree; exportAsHtml] entitled: 'Exportar como HTML' categorized: 'Arbol'; - act: [self saveWorkingTree; exportAsLatex] entitled: 'Exportar como LaTeX' categorized: 'Arbol'; - act: [self saveWorkingTree; exportAsPdf] entitled: 'Exportar como PDF' categorized: 'Arbol'; - act: [self viewExportedHtml] entitled: 'Ver HTML' categorized: 'Arbol'; - act: [self messageNotImplementedYet] entitled: 'Ver PDF' categorized: 'Arbol'; - - "For nodes" - act: [:treePresentation | - (treePresentation selection isNotNil) - ifTrue: [self copyNodeIntoCache: treePresentation selection]. - treePresentation update] entitled: 'Copiar nodo' categorized: 'Nodo'; - act: [:treePresentation | - (treePresentation selection isNotNil) - ifTrue: [self replaceContentsFromCache: treePresentation selection]. - treePresentation update] entitled: 'Pegar nodo' categorized: 'Nodo'; - - "For tags" - act: [:treePresentation | - (treePresentation selection isNotNil) - ifTrue: [self addTagTo: treePresentation selection]] - entitled: 'Etiquetar nodo como...' categorized: 'Etiquetas'; - act: [:treePresentation | - (treePresentation selection isNotNil) - ifTrue: [ - treePresentation selection tagAs: nil. - browser update. - ]] - entitled: 'Desetiquetar nodo como...' categorized: 'Etiquetas'; - act: [self showTagsAvailable] entitled: 'Ver disponibles' categorized: 'Etiquetas'; - act: [self addToTagsAvailable] entitled: 'Agregar a disponibles' categorized: 'Etiquetas'. -] - -{ #category : #persistence } -GrafoscopioBrowser >> viewExportedHtml [ - "Exports the current tree to HTML, using the same name but different extension (.html)" - | htmlFileLocation | - htmlFileLocation := ((workingFile parent) / workingFile basenameWithoutExtension) fullName, '.html'. - Smalltalk platform name = 'unix' - ifTrue: [OSProcess command: 'xdg-open ', htmlFileLocation]. - Smalltalk platform name = 'Win32' - ifTrue: [OSProcess command: 'explorer ', htmlFileLocation]. - Smalltalk platform name = 'Mac OS' - ifTrue: [OSProcess command: 'open ', htmlFileLocation]. - -] diff --git a/repository/Grafoscopio/GrafoscopioNode.class.st b/repository/Grafoscopio/GrafoscopioNode.class.st index 2e02c07..9f64e87 100644 --- a/repository/Grafoscopio/GrafoscopioNode.class.st +++ b/repository/Grafoscopio/GrafoscopioNode.class.st @@ -95,6 +95,15 @@ GrafoscopioNode class >> specialWords [ ^ #('%config' '%abstract' '%invisible' '%idea' '%footnote' 'nuevoNodo' '%embed' '%item'). ] +{ #category : #operation } +GrafoscopioNode >> addLink: anUrl [ + "anUrl is a string" + + (self links includes: anUrl) + ifFalse: [ self links add: anUrl ] + +] + { #category : #'add/remove nodes' } GrafoscopioNode >> addNode: aNode [ "Adds the given node to the receivers collection of children, and sets this object as the parent @@ -178,7 +187,7 @@ GrafoscopioNode >> asMarkdown [ self metadataAsYamlIn: markdownOutput. (self preorderTraversal) do: [ :eachNode | (eachNode level > 0) - ifTrue: [(eachNode hasAncestorTaggedAs: 'invisible') | (eachNode tags = 'invisible') + ifTrue: [(eachNode hasAncestorTaggedAs: 'invisible') | (eachNode tags includes: 'invisible') ifFalse: [ markdownOutput nextPutAll: (eachNode markdownContent) ]]]. ^markdownOutput contents ] @@ -208,6 +217,7 @@ GrafoscopioNode >> becomeDefaultTestTree [ node1 := self class new header: 'Markup'; body: 'I am just a node with markup'; + tagAs: 'text'; links: 'temp.md'; level: 1. node2 := self class new @@ -216,11 +226,13 @@ GrafoscopioNode >> becomeDefaultTestTree [ tagAs: 'código'. node3 := self class new header: 'Child'; - body: 'Just testing'. + body: 'Just testing'; + tagAs: 'text'. node1 addNode: node3. node4 := self class new header: 'Something'; - body: 'else'. + body: 'else'; + tagAs: 'text'. node1 addNode: node4. self addNode: node1; @@ -231,11 +243,14 @@ GrafoscopioNode >> becomeDefaultTestTree [ GrafoscopioNode >> becomeDefaultTree [ "I create a starting tree for all Grafoscopio notebooks with just one textual node as child." | node1 | - self level: 0. - self header: 'Arbol principal'. - node1 := GrafoscopioNode - header: 'Node 1' - body: ''. + self + level: 0; + header: 'Arbol principal'; + tagAs: 'código'. + node1 := self class new + header: 'Node 1'; + body: ''; + tagAs: 'text'. self addNode: node1. ] @@ -363,7 +378,7 @@ GrafoscopioNode >> embedNodes [ | temporalBody | temporalBody := self body. self embeddedNodes ifNotNil: [ self embeddedNodes do: [ :each | - each tags = 'código' + (each isTaggedAs: 'código') ifFalse: [temporalBody := temporalBody copyReplaceAll: (each header) with: each body] ifTrue: [temporalBody := temporalBody copyReplaceAll: (each header) with: each bodyAsCode]]]. ^ temporalBody @@ -465,9 +480,9 @@ GrafoscopioNode >> hasAncestorHeaderWith: aSpecialWord [ GrafoscopioNode >> hasAncestorTaggedAs: aSpecialWord [ "Looks if the receptor node has an ancestor with a header with 'aSpecialWord' in its tags" - self ancestors detect: [:eachAncestor | eachAncestor tags = aSpecialWord ] ifFound: [^true ] ifNone: [^false ]. - - + self ancestors detect: [:eachAncestor | eachAncestor tags includes: aSpecialWord ] + ifFound: [^true ] + ifNone: [^false ]. ] { #category : #accessing } @@ -526,7 +541,7 @@ GrafoscopioNode >> icon: aSymbol [ ] { #category : #importing } -GrafoscopioNode >> importLinkContent [ +GrafoscopioNode >> importHtmlLink [ "I take the last link and import its contents in node body. " self links last asUrl host = 'ws.stfx.eu' ifTrue: [ ^ self ]. self @@ -559,6 +574,11 @@ GrafoscopioNode >> isEmpty [ body ifNil: [ ^ true ] ifNotNil: [ ^ false ] ] +{ #category : #operation } +GrafoscopioNode >> isTaggedAs: aString [ + ^ self tags includes: aString +] + { #category : #exporting } GrafoscopioNode >> itemAsMarkdownInto: aStream [ "I export a node with %item in its header as valid Pandoc's markdown @@ -893,8 +913,8 @@ GrafoscopioNode >> selectMarkdownSubtreesToExport [ { #category : #accessing } GrafoscopioNode >> specModelClass [ - self tags = 'código' ifTrue: [^GrafoscopioCodeModel]. - self tags = 'johan' ifTrue:[^GrafoscopioButtonModel]. + (self isTaggedAs: 'código') ifTrue: [^GrafoscopioCodeModel]. + (self isTaggedAs: 'johan') ifTrue:[^GrafoscopioButtonModel]. "por defecto" ^ GrafoscopioTextModel ] @@ -904,13 +924,21 @@ GrafoscopioNode >> tagAs: aTag [ "Tags the recipient node with aTag. For the moment we will have only one tag. In the future we will have several and there will be rules to know how tags interact with each other" - tags := aTag. + (self tags includes: aTag) + ifFalse: [ self tags add: aTag ] + ] { #category : #accessing } GrafoscopioNode >> tags [ - "Returns the receiver tags. For the moment is just one... yes silly, but will be extenden properly" - + "Returns the receiver tags. For the moment is just one... yes silly, but will be extended properly" + | migration | + tags isString + ifTrue: [ + migration := tags. + tags := OrderedCollection new. + tags add: migration ]. + tags ifNil: [ tags := OrderedCollection new ]. ^ tags ] @@ -921,6 +949,18 @@ GrafoscopioNode >> title [ ^ header ] +{ #category : #operation } +GrafoscopioNode >> toggleCodeText [ + "Some tags are exclusionary. + For example a node can not be tagged as text and as 'code' (código) simultaneosly. + In that case, I replace the ocurrence of one tag by the other to warranty that both are not + in the same node." + (self isTaggedAs: 'text') + ifTrue: [ ^ self tags replaceAll: 'text' with: 'código'. ]. + (self isTaggedAs: 'código') + ifTrue: [ ^ self tags replaceAll: 'código' with: 'text'. ]. +] + { #category : #operation } GrafoscopioNode >> visitLastLink [ self lastLink = '' diff --git a/repository/Grafoscopio/GrafoscopioNotebook.class.st b/repository/Grafoscopio/GrafoscopioNotebook.class.st index 61f50d0..48771ce 100644 --- a/repository/Grafoscopio/GrafoscopioNotebook.class.st +++ b/repository/Grafoscopio/GrafoscopioNotebook.class.st @@ -244,6 +244,19 @@ GrafoscopioNotebook >> header: anObject [ header := anObject ] +{ #category : #operation } +GrafoscopioNotebook >> importLinkContent [ + "I see if a node header is an url located at 'http://ws.stfx.eu', wich means that is a shared + workspace, and convert the node body to an interactive playground" + | currentNode nodeContent | + currentNode := tree highlightedItem. + currentNode ifNil: [ ^ self ]. + nodeContent := currentNode content. + nodeContent importPlaygroundLink. + nodeContent importHtmlLink. + self updateBodyFor: currentNode +] + { #category : #initialization } GrafoscopioNotebook >> initialize [ super initialize. @@ -264,11 +277,7 @@ GrafoscopioNotebook >> initializePresenter [ ifFalse: [ (tree highlightedItem) content header: arg. tree roots: tree roots]]. - links whenTextChanged: [ :arg | - ((tree highlightedItem content links) includes: arg) - ifFalse: [ - (tree highlightedItem) content links add: arg. - self updateForSpecialLinks]] + links whenTextChanged: [ :arg | tree highlightedItem content addLink: arg] ] { #category : #initialization } @@ -621,138 +630,156 @@ GrafoscopioNotebook >> subtreeAsMarkdownFor: aNode [ GrafoscopioNotebook >> toggleCodeNode [ | currentNode | currentNode := tree highlightedItem. - (currentNode content tags = 'código') - ifTrue: [ currentNode content tagAs: '' ] - ifFalse: [ currentNode content tagAs: 'código' ]. + currentNode content toggleCodeText. self updateBodyFor: currentNode. ] { #category : #initialization } GrafoscopioNotebook >> topBar [ - ^MenuModel new - addGroup: [ :group | - group addItem: [ :item | - item - name: 'Notebook'; - icon: Smalltalk ui icons smallObjects; - subMenu: self notebookSubMenu ]. - group addItem: [ :item | - item - name: 'Project'; - icon: Smalltalk ui icons catalog; - subMenu: self projectSubMenu ] ]; - addGroup: [ :group | - group addItem: [ :item | - item - name: nil; - description: 'Save notebook'; - icon: Smalltalk ui icons glamorousSave; - action: [ self saveWorkingNotebook ] ]. - group addItem: [ :item | - item - name: nil; - description: 'Export all markdown subtrees'; - icon: Smalltalk ui icons glamorousMore; - action: [ self exportAllSubtreesAsMarkdow ] ]. - group addItem: [ :item | - item - name: nil; - description: 'Cut'; - icon: Smalltalk ui icons smallCut; - action: [ self cutNodeToClipboard ] ]. - group addItem: [ :item | - item - name: nil; - description: 'Copy'; - icon: Smalltalk ui icons smallCopy; - action: [ self copyNodeToClipboard ] ]. - group addItem: [ :item | - item - name: nil; - description: 'Paste'; - icon: Smalltalk ui icons smallPaste; - action: [ self pasteNodeFromClipboard ] ]]; - addGroup: [ :group | - group addItem: [ :item | - item - name: nil; - description: 'Add node'; - icon: MendaIcons new plusIcon; - action: [ self addNode ] ]. - group addItem: [ :item | - item - name: nil; - description: 'Delete node'; - icon: MendaIcons new minusIcon; - action: [ self removeNode ] ]. - group addItem: [ :item | - item - name: nil; - description: 'Move node up'; - icon: MendaIcons new arrowUpIcon; - action: [ self moveNodeBefore ] ]. - group addItem: [ :item | - item - name: nil; - description: 'Move node down'; - icon: MendaIcons new arrowDownIcon; - action: [ self moveNodeAfter ] ]. - group addItem: [ :item | - item - name: nil; - description: 'Move node left'; - icon: MendaIcons new arrowLeftIcon; - action: [ self promoteNode ] ]. - group addItem: [ :item | - item - name: nil; - description: 'Move node right'; - icon: MendaIcons new arrowRightIcon; - action: [ self demoteNode ] ]]; - addGroup: [ :group | - group addItem: [ :item | - item - name: nil; - description: 'Togle: code <--> text'; - icon: MendaIcons new smalltalkCodeIcon; - action: [ self toggleCodeNode ] ]. - group addItem: [ :item | - item - name: nil; - description: 'Visit link'; - icon: Smalltalk ui icons glamorousRight; - action: [ self visitNodeLink ] ]. - group addItem: [ :item | - item - name: nil; - description: 'Reload link'; - icon: Smalltalk ui icons glamorousRefresh; - action: [ self updateForSpecialLinks ] ]. - group addItem: [ :item | - item - name: nil; - description: 'Tag as...'; - icon: MendaIcons new tagAddIcon; - action: [ self inform: 'To be implemented...' ] ]. - group addItem: [ :item | - item - name: nil; - description: 'Untag ....'; - icon: MendaIcons new tagMinusIcon; - action: [ self inform: 'To be implemented...' ] ]. - group addItem: [ :item | - item - name: nil; - description: 'Edit tags...'; - icon: FontAwesomeIcons new tagsIcon; - action: [ self inform: 'To be implemented...' ] ]]; - addGroup: [ :debug | - debug addItem: [ :item | - item - name: nil; - description: 'Debug'; - icon: Smalltalk ui icons glamorousBug; - action: [ self debugWithSelector: self debugMessage ] ]] + ^ MenuModel new + addGroup: [ :group | + group + addItem: [ :item | + item + name: 'Notebook'; + icon: #smallObjects asIcon; + subMenu: self notebookSubMenu ]. + group + addItem: [ :item | + item + name: 'Project'; + icon: #catalog asIcon; + subMenu: self projectSubMenu ] ]; + addGroup: [ :group | + group + addItem: [ :item | + item + name: nil; + description: 'Save notebook'; + icon: #glamorousSave asIcon; + action: [ self saveWorkingNotebook ] ]. + group + addItem: [ :item | + item + name: nil; + description: 'Export all markdown subtrees'; + icon: #glamorousMore asIcon; + action: [ self exportAllSubtreesAsMarkdow ] ]. + group + addItem: [ :item | + item + name: nil; + description: 'Cut'; + icon: #smallCut asIcon; + action: [ self cutNodeToClipboard ] ]. + group + addItem: [ :item | + item + name: nil; + description: 'Copy'; + icon: #smallCopy asIcon; + action: [ self copyNodeToClipboard ] ]. + group + addItem: [ :item | + item + name: nil; + description: 'Paste'; + icon: #smallPaste asIcon; + action: [ self pasteNodeFromClipboard ] ] ]; + addGroup: [ :group | + group + addItem: [ :item | + item + name: nil; + description: 'Add node'; + icon: MendaIcons new plusIcon; + action: [ self addNode ] ]. + group + addItem: [ :item | + item + name: nil; + description: 'Delete node'; + icon: MendaIcons new minusIcon; + action: [ self removeNode ] ]. + group + addItem: [ :item | + item + name: nil; + description: 'Move node up'; + icon: MendaIcons new arrowUpIcon; + action: [ self moveNodeBefore ] ]. + group + addItem: [ :item | + item + name: nil; + description: 'Move node down'; + icon: MendaIcons new arrowDownIcon; + action: [ self moveNodeAfter ] ]. + group + addItem: [ :item | + item + name: nil; + description: 'Move node left'; + icon: MendaIcons new arrowLeftIcon; + action: [ self promoteNode ] ]. + group + addItem: [ :item | + item + name: nil; + description: 'Move node right'; + icon: MendaIcons new arrowRightIcon; + action: [ self demoteNode ] ] ]; + addGroup: [ :group | + group + addItem: [ :item | + item + name: nil; + description: 'Toggle: code <--> text'; + icon: MendaIcons new smalltalkCodeIcon; + action: [ self toggleCodeNode ] ]. + group + addItem: [ :item | + item + name: nil; + description: 'Visit link'; + icon: #glamorousRight asIcon; + action: [ self visitNodeLink ] ]. + group + addItem: [ :item | + item + name: nil; + description: 'Reload link'; + icon: #glamorousRefresh asIcon; + action: [ self importLinkContent ] ]. + group + addItem: [ :item | + item + name: nil; + description: 'Tag as...'; + icon: MendaIcons new tagAddIcon; + action: [ self inform: 'To be implemented...' ] ]. + group + addItem: [ :item | + item + name: nil; + description: 'Untag ....'; + icon: MendaIcons new tagMinusIcon; + action: [ self inform: 'To be implemented...' ] ]. + group + addItem: [ :item | + item + name: nil; + description: 'Edit tags...'; + icon: FontAwesomeIcons new tagsIcon; + action: [ self inform: 'To be implemented...' ] ] ]; + addGroup: [ :debug | + debug + addItem: [ :item | + item + name: nil; + description: 'Debug'; + icon: #glamorousBug asIcon; + action: [ self debugWithSelector: self debugMessage ] ] ] ] { #category : #accessing } @@ -780,19 +807,6 @@ GrafoscopioNotebook >> updateBodyFor: aNodeContainer [ self buildWithSpecLayout: self class defaultSpec ] -{ #category : #operation } -GrafoscopioNotebook >> updateForSpecialLinks [ - "I see if a node header is an url located at 'http://ws.stfx.eu', wich means that is a shared - workspace, and convert the node body to an interactive playground" - | currentNode nodeContent | - currentNode := tree highlightedItem. - currentNode ifNil: [ ^ self ]. - nodeContent := currentNode content. - nodeContent importPlaygroundLink. - nodeContent importLinkContent. - self updateBodyFor: currentNode -] - { #category : #'editing nodes' } GrafoscopioNotebook >> visitNodeLink [