Grafoscopio/src/Grafoscopio/GrafoscopioNode.class.st

419 lines
11 KiB
Smalltalk

"
An UbakyeNode is and administrator of all node operations in a tree.
Instance Variables
node: <Object>
node
- xxxxx
"
Class {
#name : #GrafoscopioNode,
#superclass : #Object,
#instVars : [
'header',
'headers',
'key',
'icon',
'body',
'children',
'parent',
'node',
'level',
'nodesInPreorder'
],
#category : #'Grafoscopio-Model'
}
{ #category : #'instance creation' }
GrafoscopioNode class >> header: aHeader body: aText [
"Create a new instance with given header and body"
^(self new)
header: aHeader;
body: aText;
yourself.
]
{ #category : #'instance creation' }
GrafoscopioNode class >> header: aHeader icon: anIcon body: aText [
"Create a new instances with given header, icon and body"
^(self new)
header: aHeader;
icon: anIcon;
body: aText;
yourself.
]
{ #category : #'instance creation' }
GrafoscopioNode class >> named: aString [
"Create a new instance with a given header and empty body"
^(self new)
header: aString;
yourself
]
{ #category : #'as yet unclassified' }
GrafoscopioNode >> addNode: aNode [
"Adds the given node to the receivers collection of children, and sets this object as the parent
of the node"
self children add: aNode.
aNode level: (self level) + 1.
aNode parent: self.
^aNode
]
{ #category : #'as yet unclassified' }
GrafoscopioNode >> addNodeAfter [
"Adds a generic node after the given node so they become slibings of the same parent"
| genericNode |
genericNode := GrafoscopioNode
header: 'nuevoNodo' body: ''.
self parent children add: genericNode after: self.
genericNode parent: self parent.
genericNode level: self level.
]
{ #category : #'as yet unclassified' }
GrafoscopioNode >> asMarkdown [
"Exports children of the curren node as pandoc markdown, using special nodes for config options and
bibliography."
| markdownOutput |
markdownOutput := '' writeStream.
(self preorderTraversal) do: [ :eachNode | markdownOutput nextPutAll: (eachNode markdownContent) ].
^markdownOutput contents
]
{ #category : #'as yet unclassified' }
GrafoscopioNode >> asSton [
"Exports current tree as STON format"
| stonOutput |
stonOutput := '' writeStream.
stonOutput nextPutAll: (STON toStringPretty: self children).
^stonOutput contents
]
{ #category : #'as yet unclassified' }
GrafoscopioNode >> becomeDefaultTree [
| node1 node2 node3 |
self level: 0.
self header: 'Arbol principal'.
node1 := GrafoscopioNode
header: 'Nodo 1'
body: 'Texto 1'.
node2 := GrafoscopioNode
header: 'Nodo 2'
body: 'Texto 2'.
node3 := GrafoscopioNode
header: 'Nodo 3'
body: 'Texto 3'.
self
addNode: node1;
addNode: node2.
node2 addNode: node3.
]
{ #category : #accessing }
GrafoscopioNode >> body [
"Returns the receivers body"
^ body
]
{ #category : #accessing }
GrafoscopioNode >> body: anObject [
"Sets the receivers body to the given object"
body := anObject
]
{ #category : #accessing }
GrafoscopioNode >> children [
"Returns the receivers list of children"
^ children ifNil: [children := OrderedCollection new]
]
{ #category : #accessing }
GrafoscopioNode >> children: aCollection [
"Sets the receivers children"
aCollection do: [:currentNode | currentNode parent: self ].
children := aCollection.
]
{ #category : #movement }
GrafoscopioNode >> demote [
"Moves the current node down in the hierachy, making a children of its current previous slibing"
| collection index predecessor |
collection := self parent children.
index := collection indexOf: self.
(index between: 2 and: collection size)
ifTrue: [ predecessor := collection before: self.
collection remove: self.
predecessor addNode: self]
]
{ #category : #accessing }
GrafoscopioNode >> header [
"Returns the receiver header"
^ header
]
{ #category : #accessing }
GrafoscopioNode >> header: anObject [
"Sets the receivers header"
header := anObject
]
{ #category : #accessing }
GrafoscopioNode >> headers [
"Returns the headers of the receiver children"
^ headers := self children collect: [:currentNode | currentNode header ]
]
{ #category : #accessing }
GrafoscopioNode >> icon [
"Returns the receivers icon"
^icon
]
{ #category : #accessing }
GrafoscopioNode >> icon: aSymbol [
"Sets the receivers icon"
icon := aSymbol
]
{ #category : #initialization }
GrafoscopioNode >> initialize [
"Creates a empty new node"
super initialize.
self header: 'newHeader'.
self body: ''.
self key: ''
]
{ #category : #accessing }
GrafoscopioNode >> key [
"Returns a unique key identifying the receiver in the help system"
^key
]
{ #category : #accessing }
GrafoscopioNode >> key: aUniqueKey [
"Sets a unique key identifying the receiver in the help system"
key := aUniqueKey
]
{ #category : #accessing }
GrafoscopioNode >> level [
"Returns the level of the node. See the setter message for details"
^level
]
{ #category : #accessing }
GrafoscopioNode >> level: anInteger [
"Sets the node level in a hierarchy. The only node with level 0 is the root node and from there levels increase
in 1 for its direct children, 2 for its grand children and so on. Silibings nodes has the same level"
level := anInteger
]
{ #category : #'as yet unclassified' }
GrafoscopioNode >> markdownContent [
"Extracts the markdown of a node using body as content, header as title and level as hierarchical level of the title.
If special nodes types are present, converts them into proper markup to be embedded inside markdown"
| markdown configDict specialWords embedNodes |
markdown := '' writeStream.
specialWords := #('#config' '#abstract' '#invisible' '#idea' '#footnote' 'nuevoNodo' '%embed').
(self level > 0) & (specialWords includes: self header) not & (specialWords includes: ((self header findTokens: $ ) at: 1)) not
ifTrue: [
self level timesRepeat: [ markdown nextPutAll: '#' ].
markdown nextPutAll: ' '.
markdown nextPutAll: (self header copyReplaceTokens: #cr with: #lf); lf; lf.
embedNodes := self headers select: [:each | ((each findTokens: $ ) at: 1) = '%embed'].
markdown nextPutAll: (self body contents withUnixLineEndings); lf; lf].
(self header = '#config')
ifTrue: [
configDict := STON fromString: (self body).
markdown nextPutAll: '---'; lf.
markdown nextPutAll: 'title: ', (configDict at: 'title'); lf.
markdown nextPutAll: 'author: ', ((configDict at: 'author') at: 'given'), ' ', ((configDict at: 'author') at: 'family'); lf.
markdown nextPutAll: 'bibliography: ', (configDict at: 'bibliography'); lf.
markdown nextPutAll: 'abstract: ', '|'; lf; nextPutAll: (configDict at: 'abstract'); lf.
markdown nextPutAll: '---'; lf. ].
((self header findString: '#idea') = 1)
ifTrue: [markdown nextPutAll: (self body contents withInternetLineEndings); lf; lf. ].
((self header findString: '#footnote') = 1)
ifTrue: [
markdown nextPutAll: ('[^',(self header copyReplaceAll: '#footnote ' with: ''),']: ' ); lf.
markdown nextPutAll: (self body contents withInternetLineEndings); lf; lf. ].
((self header findString: '%embed') = 1)
ifTrue: "[markdown nextPutAll: (self body contents withInternetLineEndings); lf; lf. ]."
[markdown nextPutAll: (((self parent body) copyReplaceAll: (self header) with: (self body)) contents withInternetLineEndings); lf; lf. ].
^markdown contents
]
{ #category : #movement }
GrafoscopioNode >> moveAfter [
"Moves the current node a place before in the children collection where is located"
| collection index successor |
collection := self parent children.
index := collection indexOf: self.
(index between: 1 and: collection size - 1)
ifTrue: [
successor := collection after: self.
collection at: index + 1 put: self.
collection at: index put: successor]
]
{ #category : #movement }
GrafoscopioNode >> moveBefore [
"Moves the current node a place before in the children collection where is located"
| collection index predecessor |
collection := self parent children.
index := collection indexOf: self.
(index between: 2 and: collection size)
ifTrue: [
predecessor := collection before: self.
collection at: index -1 put: self.
collection at: index put: predecessor]
]
{ #category : #'instance creation' }
GrafoscopioNode >> newNode [
node := Dictionary newFrom: {
#header -> 'newHeadline'.
#body -> ''.
#children -> #()}.
^ node.
]
{ #category : #accessing }
GrafoscopioNode >> parent [
"Returns the parent of the current node"
^ parent
]
{ #category : #accessing }
GrafoscopioNode >> parent: aNode [
"A parent is a node that has the current node in its children"
parent := aNode
]
{ #category : #'as yet unclassified' }
GrafoscopioNode >> preorderTraversal [
nodesInPreorder := OrderedCollection new.
self visitedGoTo: nodesInPreorder.
^ nodesInPreorder.
]
{ #category : #movement }
GrafoscopioNode >> promote [
"Moves the current node up in the hierachy, making it a slibing of its current parent"
| collection grandparent |
collection := self parent children.
grandparent := self parent parent.
collection isNotNil & grandparent isNotNil
ifTrue: [
(grandparent children) add: self after: (self parent).
self level: (self parent) level.
self parent: grandparent.
collection remove: self.]
]
{ #category : #'as yet unclassified' }
GrafoscopioNode >> removeLastNode [
"Adds the given node to the receivers collection of children, and sets this object as the parent
of the node"
self children removeLast.
]
{ #category : #'as yet unclassified' }
GrafoscopioNode >> removeNode: aNode [
"Adds the given node to the receivers collection of children, and sets this object as the parent
of the node"
self children remove: aNode.
]
{ #category : #'as yet unclassified' }
GrafoscopioNode >> returnConfig [
"Detects a children node containing the configuration for the creation of the output files. If nothing is detected,
creates defaults for that. Pending:
- Verifying that file data in config node is accurate, and if not create the proper locations.
- Maybe there is a need to consider if it should run on all the tree, instead of a particular node."
| configString configNode configDict |
configNode := (self children) detect: [:nodeContent | nodeContent header = 'Config' ] ifNone: [ nil ].
"This part always enter for the nil option! MUST BE CORRECTED"
configNode isNil
ifTrue: [
configString := '{
"title": "Boostrapping para el objeto de investigación",
"author": {
"given": "Offray Vladimir",
"family": "Luna Cárdenas"
},
"file": {
"relative-path" : "U/Libertadores/Grafoscopio/",
"name": "bootstrapping-objeto-investigacion",
"formats": [
#ston,
#markdown
]
}
}'
]
ifFalse: [ configString := configNode body ].
configDict := STON fromString: configString.
^configDict
]
{ #category : #'as yet unclassified' }
GrafoscopioNode >> visitedGoTo: aCollection [
"Stores the current node in a collection and recursively stores its children"
aCollection add: self.
(self children isNotEmpty) & ((self header findString: '#invisible')=1) not
ifTrue: [ (self children) do: [ :eachNode | eachNode visitedGoTo: aCollection]].
]