Implementing tags in nodes.

This commit is contained in:
Offray Vladimir Luna Cárdenas 2017-08-05 17:00:38 +00:00
parent f2d6d9d515
commit f251c55464
3 changed files with 217 additions and 805 deletions

View File

@ -1,642 +0,0 @@
"
I am a graphical interface for showing trees, outlines and grafoscopio notebooks.
Instance Variables
browser: <Object>
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].
]

View File

@ -95,6 +95,15 @@ GrafoscopioNode class >> specialWords [
^ #('%config' '%abstract' '%invisible' '%idea' '%footnote' 'nuevoNodo' '%embed' '%item'). ^ #('%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' } { #category : #'add/remove nodes' }
GrafoscopioNode >> addNode: aNode [ GrafoscopioNode >> addNode: aNode [
"Adds the given node to the receivers collection of children, and sets this object as the parent "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 metadataAsYamlIn: markdownOutput.
(self preorderTraversal) do: [ :eachNode | (self preorderTraversal) do: [ :eachNode |
(eachNode level > 0) (eachNode level > 0)
ifTrue: [(eachNode hasAncestorTaggedAs: 'invisible') | (eachNode tags = 'invisible') ifTrue: [(eachNode hasAncestorTaggedAs: 'invisible') | (eachNode tags includes: 'invisible')
ifFalse: [ markdownOutput nextPutAll: (eachNode markdownContent) ]]]. ifFalse: [ markdownOutput nextPutAll: (eachNode markdownContent) ]]].
^markdownOutput contents ^markdownOutput contents
] ]
@ -208,6 +217,7 @@ GrafoscopioNode >> becomeDefaultTestTree [
node1 := self class new node1 := self class new
header: 'Markup'; header: 'Markup';
body: 'I am just a node with markup'; body: 'I am just a node with markup';
tagAs: 'text';
links: 'temp.md'; links: 'temp.md';
level: 1. level: 1.
node2 := self class new node2 := self class new
@ -216,11 +226,13 @@ GrafoscopioNode >> becomeDefaultTestTree [
tagAs: 'código'. tagAs: 'código'.
node3 := self class new node3 := self class new
header: 'Child'; header: 'Child';
body: 'Just testing'. body: 'Just testing';
tagAs: 'text'.
node1 addNode: node3. node1 addNode: node3.
node4 := self class new node4 := self class new
header: 'Something'; header: 'Something';
body: 'else'. body: 'else';
tagAs: 'text'.
node1 addNode: node4. node1 addNode: node4.
self self
addNode: node1; addNode: node1;
@ -231,11 +243,14 @@ GrafoscopioNode >> becomeDefaultTestTree [
GrafoscopioNode >> becomeDefaultTree [ GrafoscopioNode >> becomeDefaultTree [
"I create a starting tree for all Grafoscopio notebooks with just one textual node as child." "I create a starting tree for all Grafoscopio notebooks with just one textual node as child."
| node1 | | node1 |
self level: 0. self
self header: 'Arbol principal'. level: 0;
node1 := GrafoscopioNode header: 'Arbol principal';
header: 'Node 1' tagAs: 'código'.
body: ''. node1 := self class new
header: 'Node 1';
body: '';
tagAs: 'text'.
self addNode: node1. self addNode: node1.
] ]
@ -363,7 +378,7 @@ GrafoscopioNode >> embedNodes [
| temporalBody | | temporalBody |
temporalBody := self body. temporalBody := self body.
self embeddedNodes ifNotNil: [ self embeddedNodes do: [ :each | self embeddedNodes ifNotNil: [ self embeddedNodes do: [ :each |
each tags = 'código' (each isTaggedAs: 'código')
ifFalse: [temporalBody := temporalBody copyReplaceAll: (each header) with: each body] ifFalse: [temporalBody := temporalBody copyReplaceAll: (each header) with: each body]
ifTrue: [temporalBody := temporalBody copyReplaceAll: (each header) with: each bodyAsCode]]]. ifTrue: [temporalBody := temporalBody copyReplaceAll: (each header) with: each bodyAsCode]]].
^ temporalBody ^ temporalBody
@ -465,9 +480,9 @@ GrafoscopioNode >> hasAncestorHeaderWith: aSpecialWord [
GrafoscopioNode >> hasAncestorTaggedAs: aSpecialWord [ GrafoscopioNode >> hasAncestorTaggedAs: aSpecialWord [
"Looks if the receptor node has an ancestor with a header with 'aSpecialWord' in its tags" "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 } { #category : #accessing }
@ -526,7 +541,7 @@ GrafoscopioNode >> icon: aSymbol [
] ]
{ #category : #importing } { #category : #importing }
GrafoscopioNode >> importLinkContent [ GrafoscopioNode >> importHtmlLink [
"I take the last link and import its contents in node body. " "I take the last link and import its contents in node body. "
self links last asUrl host = 'ws.stfx.eu' ifTrue: [ ^ self ]. self links last asUrl host = 'ws.stfx.eu' ifTrue: [ ^ self ].
self self
@ -559,6 +574,11 @@ GrafoscopioNode >> isEmpty [
body ifNil: [ ^ true ] ifNotNil: [ ^ false ] body ifNil: [ ^ true ] ifNotNil: [ ^ false ]
] ]
{ #category : #operation }
GrafoscopioNode >> isTaggedAs: aString [
^ self tags includes: aString
]
{ #category : #exporting } { #category : #exporting }
GrafoscopioNode >> itemAsMarkdownInto: aStream [ GrafoscopioNode >> itemAsMarkdownInto: aStream [
"I export a node with %item in its header as valid Pandoc's markdown "I export a node with %item in its header as valid Pandoc's markdown
@ -893,8 +913,8 @@ GrafoscopioNode >> selectMarkdownSubtreesToExport [
{ #category : #accessing } { #category : #accessing }
GrafoscopioNode >> specModelClass [ GrafoscopioNode >> specModelClass [
self tags = 'código' ifTrue: [^GrafoscopioCodeModel]. (self isTaggedAs: 'código') ifTrue: [^GrafoscopioCodeModel].
self tags = 'johan' ifTrue:[^GrafoscopioButtonModel]. (self isTaggedAs: 'johan') ifTrue:[^GrafoscopioButtonModel].
"por defecto" "por defecto"
^ GrafoscopioTextModel ^ GrafoscopioTextModel
] ]
@ -904,13 +924,21 @@ GrafoscopioNode >> tagAs: aTag [
"Tags the recipient node with aTag. For the moment we will have only one tag. "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 In the future we will have several and there will be rules to know how tags interact with
each other" each other"
tags := aTag. (self tags includes: aTag)
ifFalse: [ self tags add: aTag ]
] ]
{ #category : #accessing } { #category : #accessing }
GrafoscopioNode >> tags [ 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 ^ tags
] ]
@ -921,6 +949,18 @@ GrafoscopioNode >> title [
^ header ^ 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 } { #category : #operation }
GrafoscopioNode >> visitLastLink [ GrafoscopioNode >> visitLastLink [
self lastLink = '' self lastLink = ''

View File

@ -244,6 +244,19 @@ GrafoscopioNotebook >> header: anObject [
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 } { #category : #initialization }
GrafoscopioNotebook >> initialize [ GrafoscopioNotebook >> initialize [
super initialize. super initialize.
@ -264,11 +277,7 @@ GrafoscopioNotebook >> initializePresenter [
ifFalse: [ ifFalse: [
(tree highlightedItem) content header: arg. (tree highlightedItem) content header: arg.
tree roots: tree roots]]. tree roots: tree roots]].
links whenTextChanged: [ :arg | links whenTextChanged: [ :arg | tree highlightedItem content addLink: arg]
((tree highlightedItem content links) includes: arg)
ifFalse: [
(tree highlightedItem) content links add: arg.
self updateForSpecialLinks]]
] ]
{ #category : #initialization } { #category : #initialization }
@ -621,138 +630,156 @@ GrafoscopioNotebook >> subtreeAsMarkdownFor: aNode [
GrafoscopioNotebook >> toggleCodeNode [ GrafoscopioNotebook >> toggleCodeNode [
| currentNode | | currentNode |
currentNode := tree highlightedItem. currentNode := tree highlightedItem.
(currentNode content tags = 'código') currentNode content toggleCodeText.
ifTrue: [ currentNode content tagAs: '' ]
ifFalse: [ currentNode content tagAs: 'código' ].
self updateBodyFor: currentNode. self updateBodyFor: currentNode.
] ]
{ #category : #initialization } { #category : #initialization }
GrafoscopioNotebook >> topBar [ GrafoscopioNotebook >> topBar [
^MenuModel new ^ MenuModel new
addGroup: [ :group | addGroup: [ :group |
group addItem: [ :item | group
item addItem: [ :item |
name: 'Notebook'; item
icon: Smalltalk ui icons smallObjects; name: 'Notebook';
subMenu: self notebookSubMenu ]. icon: #smallObjects asIcon;
group addItem: [ :item | subMenu: self notebookSubMenu ].
item group
name: 'Project'; addItem: [ :item |
icon: Smalltalk ui icons catalog; item
subMenu: self projectSubMenu ] ]; name: 'Project';
addGroup: [ :group | icon: #catalog asIcon;
group addItem: [ :item | subMenu: self projectSubMenu ] ];
item addGroup: [ :group |
name: nil; group
description: 'Save notebook'; addItem: [ :item |
icon: Smalltalk ui icons glamorousSave; item
action: [ self saveWorkingNotebook ] ]. name: nil;
group addItem: [ :item | description: 'Save notebook';
item icon: #glamorousSave asIcon;
name: nil; action: [ self saveWorkingNotebook ] ].
description: 'Export all markdown subtrees'; group
icon: Smalltalk ui icons glamorousMore; addItem: [ :item |
action: [ self exportAllSubtreesAsMarkdow ] ]. item
group addItem: [ :item | name: nil;
item description: 'Export all markdown subtrees';
name: nil; icon: #glamorousMore asIcon;
description: 'Cut'; action: [ self exportAllSubtreesAsMarkdow ] ].
icon: Smalltalk ui icons smallCut; group
action: [ self cutNodeToClipboard ] ]. addItem: [ :item |
group addItem: [ :item | item
item name: nil;
name: nil; description: 'Cut';
description: 'Copy'; icon: #smallCut asIcon;
icon: Smalltalk ui icons smallCopy; action: [ self cutNodeToClipboard ] ].
action: [ self copyNodeToClipboard ] ]. group
group addItem: [ :item | addItem: [ :item |
item item
name: nil; name: nil;
description: 'Paste'; description: 'Copy';
icon: Smalltalk ui icons smallPaste; icon: #smallCopy asIcon;
action: [ self pasteNodeFromClipboard ] ]]; action: [ self copyNodeToClipboard ] ].
addGroup: [ :group | group
group addItem: [ :item | addItem: [ :item |
item item
name: nil; name: nil;
description: 'Add node'; description: 'Paste';
icon: MendaIcons new plusIcon; icon: #smallPaste asIcon;
action: [ self addNode ] ]. action: [ self pasteNodeFromClipboard ] ] ];
group addItem: [ :item | addGroup: [ :group |
item group
name: nil; addItem: [ :item |
description: 'Delete node'; item
icon: MendaIcons new minusIcon; name: nil;
action: [ self removeNode ] ]. description: 'Add node';
group addItem: [ :item | icon: MendaIcons new plusIcon;
item action: [ self addNode ] ].
name: nil; group
description: 'Move node up'; addItem: [ :item |
icon: MendaIcons new arrowUpIcon; item
action: [ self moveNodeBefore ] ]. name: nil;
group addItem: [ :item | description: 'Delete node';
item icon: MendaIcons new minusIcon;
name: nil; action: [ self removeNode ] ].
description: 'Move node down'; group
icon: MendaIcons new arrowDownIcon; addItem: [ :item |
action: [ self moveNodeAfter ] ]. item
group addItem: [ :item | name: nil;
item description: 'Move node up';
name: nil; icon: MendaIcons new arrowUpIcon;
description: 'Move node left'; action: [ self moveNodeBefore ] ].
icon: MendaIcons new arrowLeftIcon; group
action: [ self promoteNode ] ]. addItem: [ :item |
group addItem: [ :item | item
item name: nil;
name: nil; description: 'Move node down';
description: 'Move node right'; icon: MendaIcons new arrowDownIcon;
icon: MendaIcons new arrowRightIcon; action: [ self moveNodeAfter ] ].
action: [ self demoteNode ] ]]; group
addGroup: [ :group | addItem: [ :item |
group addItem: [ :item | item
item name: nil;
name: nil; description: 'Move node left';
description: 'Togle: code <--> text'; icon: MendaIcons new arrowLeftIcon;
icon: MendaIcons new smalltalkCodeIcon; action: [ self promoteNode ] ].
action: [ self toggleCodeNode ] ]. group
group addItem: [ :item | addItem: [ :item |
item item
name: nil; name: nil;
description: 'Visit link'; description: 'Move node right';
icon: Smalltalk ui icons glamorousRight; icon: MendaIcons new arrowRightIcon;
action: [ self visitNodeLink ] ]. action: [ self demoteNode ] ] ];
group addItem: [ :item | addGroup: [ :group |
item group
name: nil; addItem: [ :item |
description: 'Reload link'; item
icon: Smalltalk ui icons glamorousRefresh; name: nil;
action: [ self updateForSpecialLinks ] ]. description: 'Toggle: code <--> text';
group addItem: [ :item | icon: MendaIcons new smalltalkCodeIcon;
item action: [ self toggleCodeNode ] ].
name: nil; group
description: 'Tag as...'; addItem: [ :item |
icon: MendaIcons new tagAddIcon; item
action: [ self inform: 'To be implemented...' ] ]. name: nil;
group addItem: [ :item | description: 'Visit link';
item icon: #glamorousRight asIcon;
name: nil; action: [ self visitNodeLink ] ].
description: 'Untag ....'; group
icon: MendaIcons new tagMinusIcon; addItem: [ :item |
action: [ self inform: 'To be implemented...' ] ]. item
group addItem: [ :item | name: nil;
item description: 'Reload link';
name: nil; icon: #glamorousRefresh asIcon;
description: 'Edit tags...'; action: [ self importLinkContent ] ].
icon: FontAwesomeIcons new tagsIcon; group
action: [ self inform: 'To be implemented...' ] ]]; addItem: [ :item |
addGroup: [ :debug | item
debug addItem: [ :item | name: nil;
item description: 'Tag as...';
name: nil; icon: MendaIcons new tagAddIcon;
description: 'Debug'; action: [ self inform: 'To be implemented...' ] ].
icon: Smalltalk ui icons glamorousBug; group
action: [ self debugWithSelector: self debugMessage ] ]] 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 } { #category : #accessing }
@ -780,19 +807,6 @@ GrafoscopioNotebook >> updateBodyFor: aNodeContainer [
self buildWithSpecLayout: self class defaultSpec 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' } { #category : #'editing nodes' }
GrafoscopioNotebook >> visitNodeLink [ GrafoscopioNotebook >> visitNodeLink [