Implementing tags in nodes.
This commit is contained in:
parent
f2d6d9d515
commit
f251c55464
@ -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].
|
||||
|
||||
]
|
@ -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 = ''
|
||||
|
@ -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
|
||||
^ MenuModel new
|
||||
addGroup: [ :group |
|
||||
group addItem: [ :item |
|
||||
group
|
||||
addItem: [ :item |
|
||||
item
|
||||
name: 'Notebook';
|
||||
icon: Smalltalk ui icons smallObjects;
|
||||
icon: #smallObjects asIcon;
|
||||
subMenu: self notebookSubMenu ].
|
||||
group addItem: [ :item |
|
||||
group
|
||||
addItem: [ :item |
|
||||
item
|
||||
name: 'Project';
|
||||
icon: Smalltalk ui icons catalog;
|
||||
icon: #catalog asIcon;
|
||||
subMenu: self projectSubMenu ] ];
|
||||
addGroup: [ :group |
|
||||
group addItem: [ :item |
|
||||
group
|
||||
addItem: [ :item |
|
||||
item
|
||||
name: nil;
|
||||
description: 'Save notebook';
|
||||
icon: Smalltalk ui icons glamorousSave;
|
||||
icon: #glamorousSave asIcon;
|
||||
action: [ self saveWorkingNotebook ] ].
|
||||
group addItem: [ :item |
|
||||
group
|
||||
addItem: [ :item |
|
||||
item
|
||||
name: nil;
|
||||
description: 'Export all markdown subtrees';
|
||||
icon: Smalltalk ui icons glamorousMore;
|
||||
icon: #glamorousMore asIcon;
|
||||
action: [ self exportAllSubtreesAsMarkdow ] ].
|
||||
group addItem: [ :item |
|
||||
group
|
||||
addItem: [ :item |
|
||||
item
|
||||
name: nil;
|
||||
description: 'Cut';
|
||||
icon: Smalltalk ui icons smallCut;
|
||||
icon: #smallCut asIcon;
|
||||
action: [ self cutNodeToClipboard ] ].
|
||||
group addItem: [ :item |
|
||||
group
|
||||
addItem: [ :item |
|
||||
item
|
||||
name: nil;
|
||||
description: 'Copy';
|
||||
icon: Smalltalk ui icons smallCopy;
|
||||
icon: #smallCopy asIcon;
|
||||
action: [ self copyNodeToClipboard ] ].
|
||||
group addItem: [ :item |
|
||||
group
|
||||
addItem: [ :item |
|
||||
item
|
||||
name: nil;
|
||||
description: 'Paste';
|
||||
icon: Smalltalk ui icons smallPaste;
|
||||
action: [ self pasteNodeFromClipboard ] ]];
|
||||
icon: #smallPaste asIcon;
|
||||
action: [ self pasteNodeFromClipboard ] ] ];
|
||||
addGroup: [ :group |
|
||||
group addItem: [ :item |
|
||||
group
|
||||
addItem: [ :item |
|
||||
item
|
||||
name: nil;
|
||||
description: 'Add node';
|
||||
icon: MendaIcons new plusIcon;
|
||||
action: [ self addNode ] ].
|
||||
group addItem: [ :item |
|
||||
group
|
||||
addItem: [ :item |
|
||||
item
|
||||
name: nil;
|
||||
description: 'Delete node';
|
||||
icon: MendaIcons new minusIcon;
|
||||
action: [ self removeNode ] ].
|
||||
group addItem: [ :item |
|
||||
group
|
||||
addItem: [ :item |
|
||||
item
|
||||
name: nil;
|
||||
description: 'Move node up';
|
||||
icon: MendaIcons new arrowUpIcon;
|
||||
action: [ self moveNodeBefore ] ].
|
||||
group addItem: [ :item |
|
||||
group
|
||||
addItem: [ :item |
|
||||
item
|
||||
name: nil;
|
||||
description: 'Move node down';
|
||||
icon: MendaIcons new arrowDownIcon;
|
||||
action: [ self moveNodeAfter ] ].
|
||||
group addItem: [ :item |
|
||||
group
|
||||
addItem: [ :item |
|
||||
item
|
||||
name: nil;
|
||||
description: 'Move node left';
|
||||
icon: MendaIcons new arrowLeftIcon;
|
||||
action: [ self promoteNode ] ].
|
||||
group addItem: [ :item |
|
||||
group
|
||||
addItem: [ :item |
|
||||
item
|
||||
name: nil;
|
||||
description: 'Move node right';
|
||||
icon: MendaIcons new arrowRightIcon;
|
||||
action: [ self demoteNode ] ]];
|
||||
action: [ self demoteNode ] ] ];
|
||||
addGroup: [ :group |
|
||||
group addItem: [ :item |
|
||||
group
|
||||
addItem: [ :item |
|
||||
item
|
||||
name: nil;
|
||||
description: 'Togle: code <--> text';
|
||||
description: 'Toggle: code <--> text';
|
||||
icon: MendaIcons new smalltalkCodeIcon;
|
||||
action: [ self toggleCodeNode ] ].
|
||||
group addItem: [ :item |
|
||||
group
|
||||
addItem: [ :item |
|
||||
item
|
||||
name: nil;
|
||||
description: 'Visit link';
|
||||
icon: Smalltalk ui icons glamorousRight;
|
||||
icon: #glamorousRight asIcon;
|
||||
action: [ self visitNodeLink ] ].
|
||||
group addItem: [ :item |
|
||||
group
|
||||
addItem: [ :item |
|
||||
item
|
||||
name: nil;
|
||||
description: 'Reload link';
|
||||
icon: Smalltalk ui icons glamorousRefresh;
|
||||
action: [ self updateForSpecialLinks ] ].
|
||||
group addItem: [ :item |
|
||||
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 |
|
||||
group
|
||||
addItem: [ :item |
|
||||
item
|
||||
name: nil;
|
||||
description: 'Untag ....';
|
||||
icon: MendaIcons new tagMinusIcon;
|
||||
action: [ self inform: 'To be implemented...' ] ].
|
||||
group addItem: [ :item |
|
||||
group
|
||||
addItem: [ :item |
|
||||
item
|
||||
name: nil;
|
||||
description: 'Edit tags...';
|
||||
icon: FontAwesomeIcons new tagsIcon;
|
||||
action: [ self inform: 'To be implemented...' ] ]];
|
||||
action: [ self inform: 'To be implemented...' ] ] ];
|
||||
addGroup: [ :debug |
|
||||
debug addItem: [ :item |
|
||||
debug
|
||||
addItem: [ :item |
|
||||
item
|
||||
name: nil;
|
||||
description: 'Debug';
|
||||
icon: Smalltalk ui icons glamorousBug;
|
||||
action: [ self debugWithSelector: self debugMessage ] ]]
|
||||
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 [
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user