Implementing tags in nodes.

This commit is contained in:
Offray Vladimir Luna Cárdenas 2017-08-05 17:00:38 +00:00 committed by SantiagoBragagnolo
parent a05669966e
commit eaee95e051
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').
]
{ #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 = ''

View File

@ -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 [