Going to a even more aggresive refactor :-o
This commit is contained in:
parent
6a92669efd
commit
b61a9e83de
@ -44,7 +44,7 @@ GfUIHelpers class >> addToHelpMenu: aGrafoscopioNotebook [
|
|||||||
ifNone: [
|
ifNone: [
|
||||||
self helpMenu
|
self helpMenu
|
||||||
add: (metadata at: 'shortTitle')
|
add: (metadata at: 'shortTitle')
|
||||||
target: [ GrafoscopioNewNotebook open: nbFile ]
|
target: [ GrafoscopioNotebook open: nbFile ]
|
||||||
selector: #value ] ].
|
selector: #value ] ].
|
||||||
self updateUI
|
self updateUI
|
||||||
]
|
]
|
||||||
@ -170,7 +170,7 @@ GfUIHelpers class >> openFromRecentlyUsed [
|
|||||||
selection := UIManager default
|
selection := UIManager default
|
||||||
chooseFrom: recentNotebooksReversed title: 'Choose a notebook...'.
|
chooseFrom: recentNotebooksReversed title: 'Choose a notebook...'.
|
||||||
selection > 0
|
selection > 0
|
||||||
ifTrue: [ GrafoscopioNewNotebook new openFromFile: (recentNotebooksReversed at: selection)]
|
ifTrue: [ GrafoscopioNotebook new openFromFile: (recentNotebooksReversed at: selection)]
|
||||||
ifFalse: [ self inform: 'No notebook selected!' ]
|
ifFalse: [ self inform: 'No notebook selected!' ]
|
||||||
]
|
]
|
||||||
ifEmpty: [self messageNoRecentDocuments]
|
ifEmpty: [self messageNoRecentDocuments]
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
|
"
|
||||||
|
Just an abstract node.
|
||||||
|
"
|
||||||
Class {
|
Class {
|
||||||
#name : #GrafoscopioAbstractNode,
|
#name : #GrafoscopioAbstractNode,
|
||||||
#superclass : #Object,
|
#superclass : #Object,
|
||||||
#instVars : [
|
#instVars : [
|
||||||
'id',
|
|
||||||
'header',
|
|
||||||
'created',
|
'created',
|
||||||
'edited',
|
'edited',
|
||||||
'parent',
|
'tags',
|
||||||
'tags'
|
'order',
|
||||||
|
'name'
|
||||||
],
|
],
|
||||||
#classInstVars : [
|
#classInstVars : [
|
||||||
'clipboard'
|
'clipboard'
|
||||||
@ -15,67 +17,24 @@ Class {
|
|||||||
#category : 'Grafoscopio-Model'
|
#category : 'Grafoscopio-Model'
|
||||||
}
|
}
|
||||||
|
|
||||||
{ #category : #utility }
|
|
||||||
GrafoscopioAbstractNode class >> cleanTreeRootReferences [
|
|
||||||
|
|
||||||
| ref |
|
|
||||||
clipboard ifNil: [ ^ self ].
|
|
||||||
clipboard children ifNil: [ ^ self ].
|
|
||||||
clipboard preorderTraversal allButFirstDo: [ :n |
|
|
||||||
ref := n.
|
|
||||||
n level - 1 timesRepeat: [ ref := ref parent ].
|
|
||||||
ref parent = clipboard parent ifTrue: [ ref parent: nil ]].
|
|
||||||
clipboard parent: nil.
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioAbstractNode class >> clipboard [
|
|
||||||
^ clipboard
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioAbstractNode class >> clipboard: anObject [
|
|
||||||
clipboard := anObject
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #utility }
|
|
||||||
GrafoscopioAbstractNode class >> contentProviders [
|
|
||||||
"I list the domains of certain providers that are treated specially, because they
|
|
||||||
store and offer content like Smalltalk playgrounds or source code, that can be used
|
|
||||||
in particular ways while importing or exporting content in a node."
|
|
||||||
|
|
||||||
^ Dictionary new
|
|
||||||
at: 'playgrounds' put: #('ws.stfx.eu');
|
|
||||||
at: 'fossil' put: #('mutabit.com/repos.fossil');
|
|
||||||
at: 'etherpads' put: #('pad.tupale.co' );
|
|
||||||
yourself.
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #testing }
|
{ #category : #testing }
|
||||||
GrafoscopioAbstractNode class >> isAbstract [
|
GrafoscopioAbstractNode class >> isAbstract [
|
||||||
^ self = GrafoscopioAbstractNode
|
^ self = GrafoscopioAbstractNode
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #utility }
|
{ #category : #testing }
|
||||||
GrafoscopioAbstractNode class >> specialWords [
|
GrafoscopioAbstractNode class >> isLeaf [
|
||||||
"I return a list of word that were used in the first versions of Grafoscopio to mark node
|
^ false
|
||||||
headers to indicate special ways to handle them and their node contents.
|
|
||||||
Previous versions of first notebooks stored in Grafoscopio using this convention should be
|
|
||||||
migrated to newer versions where tags are used for the same function with simpler code"
|
|
||||||
|
|
||||||
^ #('%config' '%abstract' '%invisible' '%idea' '%footnote' '%metadata' '%output' '%embed' '%item').
|
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'add/remove nodes' }
|
{ #category : #testing }
|
||||||
GrafoscopioAbstractNode >> addNodeAfterMe: genericNode [
|
GrafoscopioAbstractNode class >> showInMenu [
|
||||||
"Adds a generic node after the given node so they become slibings of the same parent"
|
^ false
|
||||||
|
]
|
||||||
|
|
||||||
self parent
|
{ #category : #accessing }
|
||||||
ifNil: [ self children add: genericNode.
|
GrafoscopioAbstractNode >> addChild: aBlock ofClass: aClass [
|
||||||
genericNode parent: self ]
|
self subclassResponsibility
|
||||||
ifNotNil: [ self parent children add: genericNode after: self.
|
|
||||||
genericNode parent: self parent ].
|
|
||||||
^ genericNode
|
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
@ -88,11 +47,6 @@ GrafoscopioAbstractNode >> addTag: aTag [
|
|||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'as yet unclassified' }
|
|
||||||
GrafoscopioAbstractNode >> content [
|
|
||||||
self subclassResponsibility
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
GrafoscopioAbstractNode >> created [
|
GrafoscopioAbstractNode >> created [
|
||||||
|
|
||||||
@ -106,21 +60,6 @@ GrafoscopioAbstractNode >> created: aTimestamp [
|
|||||||
created := aTimestamp
|
created := aTimestamp
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #movement }
|
|
||||||
GrafoscopioAbstractNode >> demote [
|
|
||||||
"I move the current node down in the hierachy, making it 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 }
|
{ #category : #accessing }
|
||||||
GrafoscopioAbstractNode >> edited [
|
GrafoscopioAbstractNode >> edited [
|
||||||
^ edited
|
^ edited
|
||||||
@ -137,129 +76,27 @@ GrafoscopioAbstractNode >> edited: aTimestamp [
|
|||||||
edited := aTimestamp
|
edited := aTimestamp
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioAbstractNode >> header [
|
|
||||||
"Returns the receiver header"
|
|
||||||
|
|
||||||
^ header
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioAbstractNode >> header: anObject [
|
|
||||||
"Sets the receivers header"
|
|
||||||
|
|
||||||
header := anObject
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioAbstractNode >> id [
|
|
||||||
^id
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioAbstractNode >> id: aChecksum [
|
|
||||||
"I'm a unique identifier that changes when node content changes (i.e. header, body, links)."
|
|
||||||
|
|
||||||
id := aChecksum
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
GrafoscopioAbstractNode >> initialize [
|
GrafoscopioAbstractNode >> initialize [
|
||||||
"I create a empty new node"
|
"I create a empty new node"
|
||||||
|
|
||||||
super initialize.
|
super initialize.
|
||||||
self header: 'newHeader'.
|
|
||||||
id := UUID new.
|
|
||||||
created := DateAndTime now.
|
created := DateAndTime now.
|
||||||
edited := DateAndTime now
|
edited := DateAndTime now
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioAbstractNode >> instantiateBody [
|
|
||||||
| body |
|
|
||||||
body := self specModelClass new.
|
|
||||||
body content: self content.
|
|
||||||
^ body
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
GrafoscopioAbstractNode >> isLeaf [
|
GrafoscopioAbstractNode >> isLeaf [
|
||||||
^ true
|
^ self class isLeaf
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
GrafoscopioAbstractNode >> level [
|
GrafoscopioAbstractNode >> name [
|
||||||
"Returns the level of the node. See the setter message for details"
|
^ name
|
||||||
|
|
||||||
^ parent ifNil: [ 0 ] ifNotNil: [ 1 + parent level ]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #movement }
|
|
||||||
GrafoscopioAbstractNode >> moveDown [
|
|
||||||
"Moves the current node a place before in the children collection where is located"
|
|
||||||
|
|
||||||
self parent moveDown: self
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #movement }
|
|
||||||
GrafoscopioAbstractNode >> moveUp [
|
|
||||||
"Moves the current node a place before in the children collection where is located"
|
|
||||||
|
|
||||||
self parent moveUp: self
|
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
GrafoscopioAbstractNode >> openIn: aNotebook [
|
GrafoscopioAbstractNode >> name: aName [
|
||||||
aNotebook header text: self header.
|
name := aName
|
||||||
aNotebook
|
|
||||||
body:
|
|
||||||
(self instantiateBody
|
|
||||||
owner: aNotebook;
|
|
||||||
yourself)
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioAbstractNode >> parent [
|
|
||||||
"Returns the parent of the current node"
|
|
||||||
^ parent
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioAbstractNode >> parent: aNode [
|
|
||||||
"A parent is a node that has the current node in its children"
|
|
||||||
aNode ifNil: [
|
|
||||||
parent := aNode.
|
|
||||||
^self ].
|
|
||||||
aNode parent = self ifTrue: [ ^ self ].
|
|
||||||
parent := aNode.
|
|
||||||
(aNode children includes: self)
|
|
||||||
ifFalse: [ aNode addNode: self ]
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #movement }
|
|
||||||
GrafoscopioAbstractNode >> 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 parent: grandparent.
|
|
||||||
collection remove: self.]
|
|
||||||
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'as yet unclassified' }
|
|
||||||
GrafoscopioAbstractNode >> shouldAskBeforeRemove [
|
|
||||||
self subclassResponsibility
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'as yet unclassified' }
|
|
||||||
GrafoscopioAbstractNode >> specModelClass [
|
|
||||||
^ GrafoscopioNewTextModel
|
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
@ -281,14 +118,7 @@ GrafoscopioAbstractNode >> tags: aCollection [
|
|||||||
tags := aCollection
|
tags := aCollection
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioAbstractNode >> title [
|
|
||||||
"Returns the receiver header"
|
|
||||||
|
|
||||||
^ header size > 30 ifTrue: [ (header readStream next: 28) , '...' ] ifFalse: [ header ]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'as yet unclassified' }
|
{ #category : #'as yet unclassified' }
|
||||||
GrafoscopioAbstractNode >> updateEditionTimestamp [
|
GrafoscopioAbstractNode >> updateStamp [
|
||||||
self edited: DateAndTime now
|
self edited: DateAndTime now
|
||||||
]
|
]
|
||||||
|
54
repository/Grafoscopio/GrafoscopioBranchNode.class.st
Normal file
54
repository/Grafoscopio/GrafoscopioBranchNode.class.st
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
"
|
||||||
|
Branch node. this kind of node has no content
|
||||||
|
"
|
||||||
|
Class {
|
||||||
|
#name : #GrafoscopioBranchNode,
|
||||||
|
#superclass : #GrafoscopioLeafNode,
|
||||||
|
#instVars : [
|
||||||
|
'children'
|
||||||
|
],
|
||||||
|
#category : 'Grafoscopio-Model'
|
||||||
|
}
|
||||||
|
|
||||||
|
{ #category : #'instance creation' }
|
||||||
|
GrafoscopioBranchNode class >> isLeaf [
|
||||||
|
^ false
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
GrafoscopioBranchNode >> acceptVisitor: aGrafoscopioVisitor [
|
||||||
|
aGrafoscopioVisitor visitBranchNode: self.
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
GrafoscopioBranchNode >> acceptsChildsOfClass: aClass [
|
||||||
|
^ {GrafoscopioBranchNode.
|
||||||
|
GrafoscopioUnitNode} includes: aClass
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
GrafoscopioBranchNode >> addChild: aBlock ofClass: aClass [
|
||||||
|
(self acceptsChildsOfClass: aClass)
|
||||||
|
ifTrue: [ self children add: aBlock value ]
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
GrafoscopioBranchNode >> children [
|
||||||
|
"Returns the receivers list of children"
|
||||||
|
|
||||||
|
^ children ifNil: [ children := OrderedCollection new ]
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
GrafoscopioBranchNode >> children: aCollection [
|
||||||
|
"Sets the receivers children"
|
||||||
|
|
||||||
|
aCollection do: [:currentNode | currentNode parent: self ].
|
||||||
|
children := aCollection.
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
GrafoscopioBranchNode >> isLeaf [
|
||||||
|
^ false
|
||||||
|
]
|
@ -1,62 +1,24 @@
|
|||||||
|
"
|
||||||
|
This kind of a leafNodes holds code text.
|
||||||
|
"
|
||||||
Class {
|
Class {
|
||||||
#name : #GrafoscopioCodeNode,
|
#name : #GrafoscopioCodeNode,
|
||||||
#superclass : #GrafoscopioTrunkNode,
|
#superclass : #GrafoscopioTextNode,
|
||||||
#instVars : [
|
|
||||||
'icon',
|
|
||||||
'body'
|
|
||||||
],
|
|
||||||
#category : 'Grafoscopio-Model'
|
#category : 'Grafoscopio-Model'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{ #category : #'as yet unclassified' }
|
||||||
|
GrafoscopioCodeNode class >> icon [
|
||||||
|
^ self iconNamed:#objects
|
||||||
|
]
|
||||||
|
|
||||||
{ #category : #'as yet unclassified' }
|
{ #category : #'as yet unclassified' }
|
||||||
GrafoscopioCodeNode class >> nameForSelection [
|
GrafoscopioCodeNode class >> nameForSelection [
|
||||||
^ 'New Code Node'
|
^ 'New Code Node'
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #adding }
|
{ #category : #accessing }
|
||||||
GrafoscopioCodeNode >> addNode: aNode [
|
GrafoscopioCodeNode >> acceptVisitor: aGrafoscopioVisitor [
|
||||||
"Adds the given node to the receivers collection of children, and sets this object as the parent
|
aGrafoscopioVisitor visitCodeNode: self.
|
||||||
of the node"
|
|
||||||
"aNode parent = self ifTrue: [ ^ self ]."
|
|
||||||
self children add: aNode.
|
|
||||||
aNode parent: self.
|
|
||||||
^aNode
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'as yet unclassified' }
|
|
||||||
GrafoscopioCodeNode >> body [
|
|
||||||
^ body
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'as yet unclassified' }
|
|
||||||
GrafoscopioCodeNode >> body: aBody [
|
|
||||||
body := aBody
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'as yet unclassified' }
|
|
||||||
GrafoscopioCodeNode >> content [
|
|
||||||
^ body ifNil:[ '' ]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'as yet unclassified' }
|
|
||||||
GrafoscopioCodeNode >> header [
|
|
||||||
^ super header, ' (Code)'
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'as yet unclassified' }
|
|
||||||
GrafoscopioCodeNode >> instantiateBody [
|
|
||||||
| widget |
|
|
||||||
widget := super instantiateBody.
|
|
||||||
widget body whenTextChangedDo: [ :arg | self body: arg ].
|
|
||||||
^ widget
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'as yet unclassified' }
|
|
||||||
GrafoscopioCodeNode >> shouldAskBeforeRemove [
|
|
||||||
^ self content isNotEmpty
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'as yet unclassified' }
|
|
||||||
GrafoscopioCodeNode >> specModelClass [
|
|
||||||
^ GrafoscopioNewCodeModel
|
|
||||||
]
|
]
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
Class {
|
||||||
|
#name : #GrafoscopioDocumentEditionPerspective,
|
||||||
|
#superclass : #GrafoscopioPerspective,
|
||||||
|
#instVars : [
|
||||||
|
'tree',
|
||||||
|
'document'
|
||||||
|
],
|
||||||
|
#category : 'Grafoscopio-New-UI'
|
||||||
|
}
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
GrafoscopioDocumentEditionPerspective class >> defaultSpec [
|
||||||
|
^ SpBoxLayout newVertical
|
||||||
|
add: #toolbar height: self toolbarHeight;
|
||||||
|
add:
|
||||||
|
(SpBoxLayout newHorizontal
|
||||||
|
add: #tree width: 100;
|
||||||
|
add: #viewport;
|
||||||
|
yourself) yourself
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
GrafoscopioDocumentEditionPerspective class >> icon [
|
||||||
|
^ self iconNamed: #merge
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #'as yet unclassified' }
|
||||||
|
GrafoscopioDocumentEditionPerspective >> addNewNodeOfClass: aClass [
|
||||||
|
(tree selectedItem ifNil: [ document ])
|
||||||
|
addChild: [ self instantiateNode: aClass ]
|
||||||
|
ofClass: aClass.
|
||||||
|
self needRebuild: false.
|
||||||
|
self buildWithSpec
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
GrafoscopioDocumentEditionPerspective >> createDefaultViewportVisitor [
|
||||||
|
^ GrafoscopioViewportVisitor new
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
GrafoscopioDocumentEditionPerspective >> createViewport [
|
||||||
|
^ self createDefaultViewportVisitor createViewportFor: document into: self
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
GrafoscopioDocumentEditionPerspective >> initializeWidgets [
|
||||||
|
super initializeWidgets.
|
||||||
|
tree := self newTreeTable.
|
||||||
|
tree
|
||||||
|
addColumn: (SpStringTableColumn evaluated: #name);
|
||||||
|
children: [ :node |
|
||||||
|
node isLeaf
|
||||||
|
ifTrue: [ {} ]
|
||||||
|
ifFalse: [ node children ] ]
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #'as yet unclassified' }
|
||||||
|
GrafoscopioDocumentEditionPerspective >> instantiateNode: aClass [
|
||||||
|
aClass class = GrafoscopioUnitNode species
|
||||||
|
ifTrue: [ | name |
|
||||||
|
name := UIManager default
|
||||||
|
request: 'Unit name'
|
||||||
|
initialAnswer: 'New unit'.
|
||||||
|
^ aClass new
|
||||||
|
name: name;
|
||||||
|
yourself ].
|
||||||
|
^ aClass new
|
||||||
|
" self error: 'Unexpected class'"
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
GrafoscopioDocumentEditionPerspective >> updateModel: aModel [
|
||||||
|
document := aModel document.
|
||||||
|
tree roots: aModel document children.
|
||||||
|
]
|
15
repository/Grafoscopio/GrafoscopioExportPerspective.class.st
Normal file
15
repository/Grafoscopio/GrafoscopioExportPerspective.class.st
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
Class {
|
||||||
|
#name : #GrafoscopioExportPerspective,
|
||||||
|
#superclass : #GrafoscopioPerspective,
|
||||||
|
#category : 'Grafoscopio-New-UI'
|
||||||
|
}
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
GrafoscopioExportPerspective class >> icon [
|
||||||
|
^ self iconNamed: #export
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
GrafoscopioExportPerspective >> createViewport [
|
||||||
|
^ self newLabel
|
||||||
|
]
|
53
repository/Grafoscopio/GrafoscopioLeafNode.class.st
Normal file
53
repository/Grafoscopio/GrafoscopioLeafNode.class.st
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
"
|
||||||
|
Leaf node. Any content node is leaf
|
||||||
|
"
|
||||||
|
Class {
|
||||||
|
#name : #GrafoscopioLeafNode,
|
||||||
|
#superclass : #GrafoscopioAbstractNode,
|
||||||
|
#instVars : [
|
||||||
|
'parent'
|
||||||
|
],
|
||||||
|
#category : 'Grafoscopio-Model'
|
||||||
|
}
|
||||||
|
|
||||||
|
{ #category : #testing }
|
||||||
|
GrafoscopioLeafNode class >> isLeaf [
|
||||||
|
^ true
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
GrafoscopioLeafNode >> acceptVisitor: aGrafoscopioVisitor [
|
||||||
|
aGrafoscopioVisitor visitLeafNode: self.
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
GrafoscopioLeafNode >> addChild: aBlock ofClass: aClass [
|
||||||
|
self error: 'Leaf nodes are abstract. '
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
GrafoscopioLeafNode >> level [
|
||||||
|
"Returns the level of the node. See the setter message for details"
|
||||||
|
|
||||||
|
^ parent ifNil: [ 0 ] ifNotNil: [ 1 + parent level ]
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
GrafoscopioLeafNode >> parent [
|
||||||
|
"Returns the parent of the current node"
|
||||||
|
^ parent
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
GrafoscopioLeafNode >> parent: aNode [
|
||||||
|
"A parent is a node that has the current node in its children"
|
||||||
|
aNode ifNil: [
|
||||||
|
parent := aNode.
|
||||||
|
^self ].
|
||||||
|
aNode parent = self ifTrue: [ ^ self ].
|
||||||
|
parent := aNode.
|
||||||
|
(aNode children includes: self)
|
||||||
|
ifFalse: [ aNode addNode: self ]
|
||||||
|
|
||||||
|
]
|
@ -29,32 +29,6 @@ GrafoscopioNewCodeModel >> content: aGrafoscopioNodeContent [
|
|||||||
body text: aGrafoscopioNodeContent
|
body text: aGrafoscopioNodeContent
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'as yet unclassified' }
|
|
||||||
GrafoscopioNewCodeModel >> extractHtmlImages [
|
|
||||||
"comment stating purpose of message"
|
|
||||||
|imgSoup imgHost imgList src|
|
|
||||||
|
|
||||||
imgList := Set new.
|
|
||||||
imgSoup := Soup fromString: self body.
|
|
||||||
(imgSoup findAllTags: 'img') do: [ :each|
|
|
||||||
src := (each attributeAt: 'src') asUrl.
|
|
||||||
(src host) ifNil: [src host: self links last asUrl removeLastPathSegment].
|
|
||||||
imgList add: src.
|
|
||||||
"imgList add: (each attributeAt: 'src') asUrl."
|
|
||||||
|
|
||||||
"OSProcess waitForCommand: 'wget ', (each attributeAt: 'src')."
|
|
||||||
"imgHost := self links last removeLastPathSegment."
|
|
||||||
|
|
||||||
"imgPath:= ((each attributeAt: 'src') asUrl). "
|
|
||||||
"ZnEasy getJpeg: (imgHost , imgPath) asUrl."
|
|
||||||
|
|
||||||
"OSProcess waitForCommand: ('mkdir ', imgPath)."
|
|
||||||
|
|
||||||
"Transcript show: ' wget ', imgPath , '/',(each attributeAt: 'src'). "
|
|
||||||
].
|
|
||||||
^imgList .
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #initialization }
|
{ #category : #initialization }
|
||||||
GrafoscopioNewCodeModel >> initializeWidgets [
|
GrafoscopioNewCodeModel >> initializeWidgets [
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -10,7 +10,7 @@ Class {
|
|||||||
{ #category : #specs }
|
{ #category : #specs }
|
||||||
GrafoscopioNewTextModel class >> defaultSpec [
|
GrafoscopioNewTextModel class >> defaultSpec [
|
||||||
^ SpBoxLayout newVertical
|
^ SpBoxLayout newVertical
|
||||||
add: #body;
|
add: #body height: 300;
|
||||||
yourself
|
yourself
|
||||||
]
|
]
|
||||||
|
|
||||||
|
179
repository/Grafoscopio/GrafoscopioPerspective.class.st
Normal file
179
repository/Grafoscopio/GrafoscopioPerspective.class.st
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
Class {
|
||||||
|
#name : #GrafoscopioPerspective,
|
||||||
|
#superclass : #SpPresenter,
|
||||||
|
#instVars : [
|
||||||
|
'toolbar',
|
||||||
|
'viewport'
|
||||||
|
],
|
||||||
|
#category : 'Grafoscopio-New-UI'
|
||||||
|
}
|
||||||
|
|
||||||
|
{ #category : #'as yet unclassified' }
|
||||||
|
GrafoscopioPerspective class >> defaultPerspective [
|
||||||
|
^ GrafoscopioDocumentEditionPerspective
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #'as yet unclassified' }
|
||||||
|
GrafoscopioPerspective class >> defaultSpec [
|
||||||
|
^ SpBoxLayout newVertical
|
||||||
|
add: #toolbar height: self toolbarHeight;
|
||||||
|
add: #viewport;
|
||||||
|
yourself
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #'as yet unclassified' }
|
||||||
|
GrafoscopioPerspective class >> isAbstract [
|
||||||
|
^ self = GrafoscopioPerspective
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #'as yet unclassified' }
|
||||||
|
GrafoscopioPerspective class >> perspectives [
|
||||||
|
^ self allSubclasses select: [ : c | c isAbstract not ]
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
GrafoscopioPerspective >> aboutToBeUninstalledFrom: aTreeNotebook [
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
GrafoscopioPerspective >> addItemTo: aGroup [
|
||||||
|
aGroup
|
||||||
|
addItem: [ :item |
|
||||||
|
item
|
||||||
|
name: 'Dynamic';
|
||||||
|
icon: (self iconNamed: #delete);
|
||||||
|
action: [ aGroup menuItems remove: item.
|
||||||
|
self needRebuild: false.
|
||||||
|
self buildWithSpec ] ].
|
||||||
|
self needRebuild: false.
|
||||||
|
self buildWithSpec
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
GrafoscopioPerspective >> addingMenu [
|
||||||
|
| menu |
|
||||||
|
menu := self newMenu.
|
||||||
|
GrafoscopioAbstractNode allSubclasses
|
||||||
|
select: [ :c | c showInMenu ]
|
||||||
|
thenDo: [ :n |
|
||||||
|
menu
|
||||||
|
addItem: [ :item |
|
||||||
|
item
|
||||||
|
name: n nameForSelection;
|
||||||
|
icon: n icon;
|
||||||
|
action: [ self addNewNodeOfClass: n ] ] ].
|
||||||
|
^ menu
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
GrafoscopioPerspective >> createToolbar [
|
||||||
|
| aMenu |
|
||||||
|
aMenu := self newMenuBar
|
||||||
|
addGroup: [ :group |
|
||||||
|
group
|
||||||
|
addItem: [ :item |
|
||||||
|
item
|
||||||
|
name: 'File';
|
||||||
|
icon: (self iconNamed: #openIcon);
|
||||||
|
subMenu: self subMenu ].
|
||||||
|
group
|
||||||
|
addItem: [ :item |
|
||||||
|
item
|
||||||
|
name: nil;
|
||||||
|
description: 'Open file';
|
||||||
|
icon: (self iconNamed: #openIcon);
|
||||||
|
action: [ self inform: 'Open File' ] ].
|
||||||
|
group
|
||||||
|
addItem: [ :item |
|
||||||
|
item
|
||||||
|
name: nil;
|
||||||
|
description: 'Save File';
|
||||||
|
icon: (self iconNamed: #smallSaveIcon);
|
||||||
|
action: [ self inform: 'Save File' ] ].
|
||||||
|
group
|
||||||
|
addItem: [ :item |
|
||||||
|
item
|
||||||
|
name: nil;
|
||||||
|
description: 'Print file';
|
||||||
|
icon: (self iconNamed: #smallPrintIcon);
|
||||||
|
action: [ self inform: 'Print file' ] ] ];
|
||||||
|
addGroup: [ :group |
|
||||||
|
group
|
||||||
|
addItem: [ :item |
|
||||||
|
item
|
||||||
|
name: nil;
|
||||||
|
description: 'Undo';
|
||||||
|
icon: (self iconNamed: #smallUndoIcon);
|
||||||
|
action: [ self inform: 'Undo' ] ].
|
||||||
|
group
|
||||||
|
addItem: [ :item |
|
||||||
|
item
|
||||||
|
name: nil;
|
||||||
|
description: 'Redo';
|
||||||
|
icon: (self iconNamed: #smallRedoIcon);
|
||||||
|
action: [ self inform: 'Redo' ] ].
|
||||||
|
group
|
||||||
|
addItem: [ :item |
|
||||||
|
item
|
||||||
|
name: '';
|
||||||
|
icon: (self iconNamed: #add);
|
||||||
|
subMenu: self addingMenu ].
|
||||||
|
|
||||||
|
];
|
||||||
|
addGroup: [ :group |
|
||||||
|
group
|
||||||
|
addItem: [ :item |
|
||||||
|
item
|
||||||
|
name: nil;
|
||||||
|
description: 'Add menu item';
|
||||||
|
icon: (self iconNamed: #add);
|
||||||
|
action: [ self addItemTo: group ] ] ].
|
||||||
|
aMenu color: Color transparent.
|
||||||
|
^ aMenu
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
GrafoscopioPerspective >> createViewport [
|
||||||
|
self subclassResponsibility
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
GrafoscopioPerspective >> initializeWidgets [
|
||||||
|
super initializeWidgets.
|
||||||
|
toolbar := self createToolbar.
|
||||||
|
viewport := self createViewport
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
GrafoscopioPerspective >> subMenu [
|
||||||
|
^ self newMenu
|
||||||
|
addItem: [ :item |
|
||||||
|
item
|
||||||
|
name: 'Open';
|
||||||
|
icon: (self iconNamed: #openIcon);
|
||||||
|
shortcut: $o meta;
|
||||||
|
action: [ self inform: 'Open' ] ];
|
||||||
|
addItem: [ :item |
|
||||||
|
item
|
||||||
|
name: 'Save';
|
||||||
|
icon: (self iconNamed: #smallSaveIcon);
|
||||||
|
shortcut: $s meta;
|
||||||
|
action: [ self inform: 'Save' ] ];
|
||||||
|
addItem: [ :item |
|
||||||
|
item
|
||||||
|
name: 'Print';
|
||||||
|
shortcut: $p meta;
|
||||||
|
icon: (self iconNamed: #smallPrintIcon);
|
||||||
|
action: [ self inform: 'Print' ] ];
|
||||||
|
addItem: [ :item |
|
||||||
|
item
|
||||||
|
name: 'Close';
|
||||||
|
shortcut: $c meta;
|
||||||
|
icon: (self iconNamed: #smallCancelIcon);
|
||||||
|
action: [ self inform: 'Kill' ] ];
|
||||||
|
yourself
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #'as yet unclassified' }
|
||||||
|
GrafoscopioPerspective >> updateModel: aModel [
|
||||||
|
]
|
21
repository/Grafoscopio/GrafoscopioProject.class.st
Normal file
21
repository/Grafoscopio/GrafoscopioProject.class.st
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
Class {
|
||||||
|
#name : #GrafoscopioProject,
|
||||||
|
#superclass : #Object,
|
||||||
|
#instVars : [
|
||||||
|
'document',
|
||||||
|
'dictionary'
|
||||||
|
],
|
||||||
|
#category : 'Grafoscopio-Model'
|
||||||
|
}
|
||||||
|
|
||||||
|
{ #category : #'as yet unclassified' }
|
||||||
|
GrafoscopioProject >> document [
|
||||||
|
^ document
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
GrafoscopioProject >> initialize [
|
||||||
|
super initialize.
|
||||||
|
document := GrafoscopioRootNode new.
|
||||||
|
dictionary := GrafoscopioRootNode new
|
||||||
|
]
|
46
repository/Grafoscopio/GrafoscopioRootNode.class.st
Normal file
46
repository/Grafoscopio/GrafoscopioRootNode.class.st
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
"
|
||||||
|
This is a root node. It represents a document.
|
||||||
|
"
|
||||||
|
Class {
|
||||||
|
#name : #GrafoscopioRootNode,
|
||||||
|
#superclass : #GrafoscopioAbstractNode,
|
||||||
|
#instVars : [
|
||||||
|
'children'
|
||||||
|
],
|
||||||
|
#category : 'Grafoscopio-Model'
|
||||||
|
}
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
GrafoscopioRootNode >> acceptVisitor: aGrafoscopioVisitor [
|
||||||
|
aGrafoscopioVisitor visitRootNode: self.
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
GrafoscopioRootNode >> acceptsChildsOfClass: aClass [
|
||||||
|
^ {GrafoscopioUnitNode} includes: aClass
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
GrafoscopioRootNode >> addChild: aBlock ofClass: aClass [
|
||||||
|
(self acceptsChildsOfClass: aClass)
|
||||||
|
ifTrue: [ self children add: aBlock value ]
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #'as yet unclassified' }
|
||||||
|
GrafoscopioRootNode >> children [
|
||||||
|
^ children
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
GrafoscopioRootNode >> initialize [
|
||||||
|
super initialize.
|
||||||
|
children := SortedCollection new
|
||||||
|
sortBlock: [ :a :b | a order < b order ];
|
||||||
|
yourself
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
GrafoscopioRootNode >> level [
|
||||||
|
^ 1
|
||||||
|
]
|
@ -1,923 +1,37 @@
|
|||||||
"
|
"
|
||||||
An UbakyeNode is and administrator of all node operations in a tree.
|
This kind of a leafNodes holds plain text.
|
||||||
|
|
||||||
Instance Variables
|
|
||||||
node: <Object>
|
|
||||||
|
|
||||||
node
|
|
||||||
- xxxxx
|
|
||||||
|
|
||||||
"
|
"
|
||||||
Class {
|
Class {
|
||||||
#name : #GrafoscopioTextNode,
|
#name : #GrafoscopioTextNode,
|
||||||
#superclass : #GrafoscopioTrunkNode,
|
#superclass : #GrafoscopioLeafNode,
|
||||||
#instVars : [
|
#instVars : [
|
||||||
'key',
|
'text'
|
||||||
'icon',
|
|
||||||
'body',
|
|
||||||
'links'
|
|
||||||
],
|
],
|
||||||
#category : 'Grafoscopio-Model'
|
#category : 'Grafoscopio-Model'
|
||||||
}
|
}
|
||||||
|
|
||||||
{ #category : #'as yet unclassified' }
|
|
||||||
GrafoscopioTextNode class >> nameForSelection [
|
|
||||||
^ 'New Text Node'
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #operation }
|
|
||||||
GrafoscopioTextNode >> addLink: anUrl [
|
|
||||||
"anUrl is a string"
|
|
||||||
|
|
||||||
(self links includes: anUrl)
|
|
||||||
ifFalse: [ self links add: anUrl ]
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #adding }
|
|
||||||
GrafoscopioTextNode >> addNode: aNode [
|
|
||||||
"Adds the given node to the receivers collection of children, and sets this object as the parent
|
|
||||||
of the node"
|
|
||||||
"aNode parent = self ifTrue: [ ^ self ]."
|
|
||||||
self children add: aNode.
|
|
||||||
aNode parent: self.
|
|
||||||
^aNode
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
GrafoscopioTextNode >> ancestors [
|
GrafoscopioTextNode class >> icon [
|
||||||
"I return a collection of all the nodes wich are ancestors of the receiver node"
|
^ self iconNamed: #workspace
|
||||||
| currentNode ancestors |
|
|
||||||
|
|
||||||
currentNode := self.
|
|
||||||
ancestors := OrderedCollection new.
|
|
||||||
[ currentNode parent notNil and: [ currentNode level > 0 ] ]
|
|
||||||
whileTrue: [
|
|
||||||
ancestors add: currentNode parent.
|
|
||||||
currentNode := currentNode parent].
|
|
||||||
ancestors := ancestors reversed.
|
|
||||||
^ ancestors
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioTextNode >> ancestorsAll [
|
|
||||||
"I return a collection of all the nodes wich are ancestors of the receiver node"
|
|
||||||
| currentNode ancestors |
|
|
||||||
|
|
||||||
currentNode := self.
|
|
||||||
ancestors := OrderedCollection new.
|
|
||||||
[ currentNode parent notNil and: [ currentNode level > 0 ] ]
|
|
||||||
whileTrue: [
|
|
||||||
ancestors add: currentNode parent.
|
|
||||||
currentNode := currentNode parent].
|
|
||||||
ancestors := ancestors reversed.
|
|
||||||
^ ancestors
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioTextNode >> ancestorsHeaders [
|
|
||||||
"Returns the headers of all the ancestors of the node.
|
|
||||||
Maybe this and 'headers' should be integrated, so both act on a collection of children instead of
|
|
||||||
having two separate methods"
|
|
||||||
| currentNode ancestors |
|
|
||||||
|
|
||||||
currentNode := self.
|
|
||||||
ancestors := OrderedCollection new.
|
|
||||||
(self level - 1)
|
|
||||||
timesRepeat: [
|
|
||||||
ancestors add: currentNode parent.
|
|
||||||
currentNode := currentNode parent.].
|
|
||||||
ancestors := ancestors reversed.
|
|
||||||
^ ancestors collect: [:ancestor | ancestor header ]
|
|
||||||
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #exporting }
|
|
||||||
GrafoscopioTextNode >> asMarkdown [
|
|
||||||
"I export children of the current node as pandoc markdown, using special nodes
|
|
||||||
accoding to tags.
|
|
||||||
Early version... tags processing should be vastly improved"
|
|
||||||
| markdownOutput |
|
|
||||||
|
|
||||||
markdownOutput := '' writeStream.
|
|
||||||
"self metadataAsYamlIn: markdownOutput."
|
|
||||||
(self preorderTraversal) do: [ :eachNode |
|
|
||||||
(eachNode level > 0)
|
|
||||||
ifTrue: [(eachNode hasAncestorTaggedAs: 'invisible')
|
|
||||||
| (eachNode tags includes: 'invisible')
|
|
||||||
ifFalse: [
|
|
||||||
markdownOutput nextPutAll: (eachNode markdownContent) ]]].
|
|
||||||
^ markdownOutput contents
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #exporting }
|
|
||||||
GrafoscopioTextNode >> asSton [
|
|
||||||
"Exports current tree as STON format"
|
|
||||||
| stonOutput |
|
|
||||||
|
|
||||||
stonOutput := '' writeStream.
|
|
||||||
stonOutput nextPutAll: (STON toStringPretty: self "flatten").
|
|
||||||
^stonOutput contents
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #exporting }
|
|
||||||
GrafoscopioTextNode >> asStonFromRoot [
|
|
||||||
"Exports current tree as STON format"
|
|
||||||
| stonOutput |
|
|
||||||
|
|
||||||
stonOutput := '' writeStream.
|
|
||||||
self flatten.
|
|
||||||
stonOutput nextPutAll: (STON toStringPretty: self children).
|
|
||||||
^stonOutput contents
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioTextNode >> asTreeNodePresenter [
|
|
||||||
| node |
|
|
||||||
node := SpTreeNodePresenter new.
|
|
||||||
node
|
|
||||||
hasChildren: [ self children isNotEmpty ];
|
|
||||||
children: [ self children collect: [ :subNode | subNode asTreeNodePresenter ] ];
|
|
||||||
content: self.
|
|
||||||
^ node
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioTextNode >> body [
|
|
||||||
"Returns the receivers body"
|
|
||||||
|
|
||||||
^ body
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioTextNode >> body: anObject [
|
|
||||||
body := anObject
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #exporting }
|
|
||||||
GrafoscopioTextNode >> bodyAsCode [
|
|
||||||
"I return the node body with proper decorators added to show them as raw code"
|
|
||||||
| codeBody |
|
|
||||||
codeBody := '' writeStream.
|
|
||||||
codeBody
|
|
||||||
nextPutAll: '~~~{.numberLines}'; lf;
|
|
||||||
nextPutAll: (self body contents asString withInternetLineEndings); lf;
|
|
||||||
nextPutAll: '~~~'; lf; lf.
|
|
||||||
^ codeBody contents
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #exporting }
|
|
||||||
GrafoscopioTextNode >> bodyAsMarkdownInto: aStream [
|
|
||||||
"I export the header as markdown using the level inside the tree to determine hierarchy
|
|
||||||
and replacing all line endings to make them Internet friendly".
|
|
||||||
self embeddedNodes ifNotNil: [ aStream nextPutAll: (self embedNodes contents asString withInternetLineEndings); crlf; crlf].
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'add/remove nodes' }
|
|
||||||
GrafoscopioTextNode >> buildPreorderCollection: 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 buildPreorderCollection: aCollection]].
|
|
||||||
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #operation }
|
|
||||||
GrafoscopioTextNode >> checksum [
|
|
||||||
"I return the SHA1SUM of the current node.
|
|
||||||
I'm used to test changes on the node contents, without including changes in the children."
|
|
||||||
| nodeCopy |
|
|
||||||
nodeCopy := self surfaceCopy.
|
|
||||||
^ self checksumFor: nodeCopy asSton.
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #utility }
|
|
||||||
GrafoscopioTextNode >> checksumFor: aText [
|
|
||||||
"I return the SHA1SUM of the current tree. I'm used to test changes on the contents
|
|
||||||
and for traceability of how the document tree is converted to other formats, as markdown."
|
|
||||||
^ (SHA1 new hashMessage: aText) hex
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #operation }
|
|
||||||
GrafoscopioTextNode >> checksumForRootSubtree [
|
|
||||||
"I return the SHA1SUM of the current tree. I'm used to test changes on the contents
|
|
||||||
and for traceability of how the document tree is converted to other formats, as markdown."
|
|
||||||
^ self checksumFor: self root flatten asStonFromRoot.
|
|
||||||
"^ (SHA1 new hashMessage: self root flatten asStonFromRoot) hex"
|
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'as yet unclassified' }
|
{ #category : #'as yet unclassified' }
|
||||||
GrafoscopioTextNode >> content [
|
GrafoscopioTextNode class >> nameForSelection [
|
||||||
^ body
|
^ 'New text node'
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #'as yet unclassified' }
|
{ #category : #'as yet unclassified' }
|
||||||
GrafoscopioTextNode >> content: aContent [
|
GrafoscopioTextNode class >> showInMenu [
|
||||||
self body: aContent
|
^ true
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'add/remove nodes' }
|
|
||||||
GrafoscopioTextNode >> copyToClipboard [
|
|
||||||
self class clipboard: self subtreeCopy.
|
|
||||||
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #operation }
|
|
||||||
GrafoscopioTextNode >> currentLink [
|
|
||||||
"TODO: This method should not only select sanitized links, but also provide ways to detect wich link
|
|
||||||
is selected from the list. For the moment, is only the last one, but probably links needs to be heavily
|
|
||||||
refactored to support this kind of operations and a better UI."
|
|
||||||
^ self sanitizeDefaultLink
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'as yet unclassified' }
|
|
||||||
GrafoscopioTextNode >> detectSelectionIndex [
|
|
||||||
"I tell which is the index of the current selected node or return the first childre
|
|
||||||
(indexed at 1) if is not found."
|
|
||||||
|
|
||||||
| root |
|
|
||||||
root := self root.
|
|
||||||
root preorderTraversal allButFirst doWithIndex: [ :currentNode :index |
|
|
||||||
currentNode isSelected ifTrue: [ ^ index ] ].
|
|
||||||
^ 1.
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'custom markup' }
|
|
||||||
GrafoscopioTextNode >> embedAll [
|
|
||||||
"This is just a previous part of the messy markDownContent. The %embed-all keyword should be revaluated.
|
|
||||||
By default a node embeds all its children. Any non-embedable content should be under a %invisible node"
|
|
||||||
"(temporalBody includesSubstring: '%embed-all')
|
|
||||||
ifFalse: [ ]
|
|
||||||
ifTrue: [
|
|
||||||
self embeddedNodes do: [ :each |
|
|
||||||
temporalBody := temporalBody copyReplaceAll: '%embed-all' with: (each body, (String with: Character cr),
|
|
||||||
'%embed-all')].
|
|
||||||
temporalBody := temporalBody copyReplaceAll: '%embed-all' with: '']"
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'custom markup' }
|
|
||||||
GrafoscopioTextNode >> embedNodes [
|
|
||||||
"I find any ocurrence of '%embed a node header' in the body of a node and replace it
|
|
||||||
by the children which have such header.
|
|
||||||
Using embedded nodes is useful to change the order in which children appear into parents body,
|
|
||||||
while exporting"
|
|
||||||
| temporalBody |
|
|
||||||
temporalBody := self body.
|
|
||||||
self embeddedNodes ifNotNil: [ self embeddedNodes do: [ :each |
|
|
||||||
(each isTaggedAs: 'código')
|
|
||||||
ifFalse: [temporalBody := temporalBody copyReplaceAll: (each header) with: each body]
|
|
||||||
ifTrue: [temporalBody := temporalBody copyReplaceAll: (each header) with: each bodyAsCode]]].
|
|
||||||
^ temporalBody
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'custom markup' }
|
|
||||||
GrafoscopioTextNode >> embeddedNodes [
|
|
||||||
^ self children select: [:each | each headerStartsWith: '%embed']
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #exporting }
|
|
||||||
GrafoscopioTextNode >> exportCodeBlockTo: aStream [
|
|
||||||
"I convert the content of a node taged as 'código' (code) as pandoc markdown and put it
|
|
||||||
into aStream."
|
|
||||||
aStream nextPutAll: ('~~~{.numberLines}'); lf.
|
|
||||||
aStream nextPutAll: (self body contents asString withInternetLineEndings); lf.
|
|
||||||
aStream nextPutAll: ('~~~'); lf;lf.
|
|
||||||
^aStream contents
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #exporting }
|
|
||||||
GrafoscopioTextNode >> exportCodeNodeTo: aStream [
|
|
||||||
"I convert the content of a node taged as 'código' (code) as pandoc markdown
|
|
||||||
and put it into aStream."
|
|
||||||
((self headerStartsWith: '%output') or: [ self headerStartsWith: '%metadata' ])
|
|
||||||
ifTrue: [ self exportCodeOutputTo: aStream ]
|
|
||||||
ifFalse: [ self exportCodeBlockTo: aStream ]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #exporting }
|
|
||||||
GrafoscopioTextNode >> exportCodeOutputTo: aStream [
|
|
||||||
"I convert the output of a node taged as 'código' (code) as pandoc markdown and
|
|
||||||
put it into aStream."
|
|
||||||
(self headerStartsWith: '%metadata') ifTrue: [ ^ self ].
|
|
||||||
aStream nextPutAll: ('~~~{.numberLines}'); lf.
|
|
||||||
aStream nextPutAll: (self output asString withInternetLineEndings); lf.
|
|
||||||
aStream nextPutAll: ('~~~'); lf;lf.
|
|
||||||
^aStream contents
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #exporting }
|
|
||||||
GrafoscopioTextNode >> exportLaTeXCodeBlockTo: aStream [
|
|
||||||
"I convert the content of a node taged as 'código' (code) as pandoc markdown and put it
|
|
||||||
into aStream.
|
|
||||||
The code block is decorated with LaTeX commands for proper syntax highlighting using pygments.
|
|
||||||
Pdf exportation requires the installation of pygments and minted package for latex"
|
|
||||||
aStream nextPutAll: ('\begin{minted}{smalltalk}'); lf.
|
|
||||||
aStream nextPutAll: (self body contents asString withInternetLineEndings); lf.
|
|
||||||
aStream nextPutAll: '\end{minted}';lf;lf.
|
|
||||||
^aStream contents
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #exporting }
|
|
||||||
GrafoscopioTextNode >> exportPreambleTo: aStream [
|
|
||||||
"comment stating purpose of message"
|
|
||||||
| configDict |
|
|
||||||
(self header = '%config')
|
|
||||||
ifTrue: [
|
|
||||||
configDict := STON fromString: (self body).
|
|
||||||
aStream nextPutAll: 'title: ', (configDict at: 'title'); lf.
|
|
||||||
aStream nextPutAll: 'author: ', ((configDict at: 'author') at: 'given'), ' ', ((configDict at: 'author') at: 'family'); lf.
|
|
||||||
aStream nextPutAll: 'bibliography: ', (configDict at: 'bibliography'); lf.
|
|
||||||
aStream nextPutAll: 'abstract: ', '|'; lf; nextPutAll: (configDict at: 'abstract'); lf]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #utility }
|
|
||||||
GrafoscopioTextNode >> find: aString andReplaceWith: anotherString [
|
|
||||||
anotherString ifNil: [ ^ self ].
|
|
||||||
self body: ((self body) copyReplaceAll: aString with: anotherString)
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #exporting }
|
|
||||||
GrafoscopioTextNode >> flatten [
|
|
||||||
"I traverse the tree looking for node bodies containing 'Text' objects and transform them to
|
|
||||||
their string content, so space is saved and storage format is DVCS friendly while serializing
|
|
||||||
them to STON"
|
|
||||||
|
|
||||||
(self preorderTraversal) do: [ :eachNode |
|
|
||||||
(eachNode body class = Text)
|
|
||||||
ifTrue: [eachNode body: (eachNode body asString)]]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #exporting }
|
|
||||||
GrafoscopioTextNode >> footnoteAsMarkdownInto: aStream [
|
|
||||||
"I export a node with %footnode in its header for valid Pandoc's markdown
|
|
||||||
and replace all line endings to make them Internet friendly.
|
|
||||||
Maybe I should include the condition about my own header, instead of leaving it to markdownCotent..."
|
|
||||||
aStream nextPutAll: ('[^',(self header copyReplaceAll: '%footnote ' with: ''),']: ' ); lf.
|
|
||||||
self body contents asString withInternetLineEndings
|
|
||||||
linesDo: [ :line | aStream nextPutAll: ' ', line; lf ].
|
|
||||||
aStream nextPutAll: String lf.
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #exporting }
|
|
||||||
GrafoscopioTextNode >> hasAncestorHeaderWith: aSpecialWord [
|
|
||||||
"Looks if the receptor node has an ancestor with a header with 'aSpecialWord' as the only or the first word"
|
|
||||||
|
|
||||||
^ (self ancestorsHeaders includes: aSpecialWord) | ((self ancestorsHeaders collect: [:eachHeader | (eachHeader findTokens: $ ) at: 1 ]) includes: aSpecialWord)
|
|
||||||
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #exporting }
|
|
||||||
GrafoscopioTextNode >> hasAncestorTaggedAs: aSpecialWord [
|
|
||||||
"Looks if the receptor node has an ancestor with a header with 'aSpecialWord' in its tags"
|
|
||||||
|
|
||||||
self ancestors detect: [:eachAncestor | eachAncestor tags includes: aSpecialWord ]
|
|
||||||
ifFound: [^true ]
|
|
||||||
ifNone: [^false ].
|
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
GrafoscopioTextNode >> hasChildren [
|
GrafoscopioTextNode >> acceptVisitor: aGrafoscopioVisitor [
|
||||||
(self children size > 0)
|
aGrafoscopioVisitor visitTextNode: self.
|
||||||
ifTrue: [ ^true ]
|
|
||||||
ifFalse: [ ^false ]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #exporting }
|
|
||||||
GrafoscopioTextNode >> headerAsMarkdownInto: aStream [
|
|
||||||
"I export the header as markdown using the level inside the tree to determine hierarchy
|
|
||||||
and replacing all line endings to make them Internet friendly"
|
|
||||||
self level timesRepeat: [ aStream nextPutAll: '#' ].
|
|
||||||
aStream nextPutAll: ' '.
|
|
||||||
aStream nextPutAll: (self header copyReplaceTokens: #cr with: #lf); crlf; crlf.
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'custom markup' }
|
|
||||||
GrafoscopioTextNode >> headerStartsWith: aString [
|
|
||||||
^ (self header findString: aString) = 1
|
|
||||||
]
|
]
|
||||||
|
|
||||||
{ #category : #accessing }
|
{ #category : #accessing }
|
||||||
GrafoscopioTextNode >> headers [
|
GrafoscopioTextNode >> text: aString [
|
||||||
"I returns the headers of the receiver children"
|
text := aString
|
||||||
^ self children collect: [:currentNode | currentNode header ]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #operation }
|
|
||||||
GrafoscopioTextNode >> htmlToMarkdown [
|
|
||||||
"I convert the node body from HTML format to Pandoc's Markdown."
|
|
||||||
| htmlFile |
|
|
||||||
(self isTaggedAs: 'código' ) ifTrue: [ ^self ].
|
|
||||||
((self headerStartsWith: '%invisible') "or:[self hasAncestorHeaderWith: '%invisible']")
|
|
||||||
ifTrue: [ ^self ].
|
|
||||||
htmlFile := FileLocator temp asFileReference / 'body.html'.
|
|
||||||
htmlFile ensureCreateFile.
|
|
||||||
htmlFile writeStreamDo: [:out | out nextPutAll: self body ].
|
|
||||||
Smalltalk platformName = 'unix'
|
|
||||||
ifTrue: [ self body: (Pandoc htmlToMarkdown: htmlFile) ].
|
|
||||||
Smalltalk platformName = 'Win32'
|
|
||||||
ifTrue: [ self shouldBeImplemented ].
|
|
||||||
htmlFile ensureDelete.
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #operation }
|
|
||||||
GrafoscopioTextNode >> htmlToMarkdownSubtree [
|
|
||||||
"I convert self and childern nodes body from HTML format to Pandoc's Markdown."
|
|
||||||
self preorderTraversal do: [ :each | each htmlToMarkdown ]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioTextNode >> icon [
|
|
||||||
"Returns the receivers icon"
|
|
||||||
|
|
||||||
^icon
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioTextNode >> icon: aSymbol [
|
|
||||||
"Sets the receivers icon"
|
|
||||||
|
|
||||||
icon := aSymbol
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #importing }
|
|
||||||
GrafoscopioTextNode >> importHtmlLink [
|
|
||||||
"I take the last link and import its contents in node body. "
|
|
||||||
| selectedLink downloadedContent |
|
|
||||||
selectedLink := self currentLink.
|
|
||||||
selectedLink asUrl host = 'ws.stfx.eu' ifTrue: [ ^ self ].
|
|
||||||
selectedLink asUrl host = 'docutopia.tupale.co'
|
|
||||||
ifTrue: [ self inform: 'Docutopia importing still not supported.'.
|
|
||||||
^ self ].
|
|
||||||
downloadedContent := (GrafoscopioUtils
|
|
||||||
downloadingFrom: selectedLink
|
|
||||||
withMessage: 'Downloading node contents...'
|
|
||||||
into: FileLocator temp).
|
|
||||||
self uploadBodyFrom: downloadedContent filteredFor: selectedLink.
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #importing }
|
|
||||||
GrafoscopioTextNode >> importPlaygroundLink [
|
|
||||||
"I take the last link and import its contents in node body.
|
|
||||||
Last links should be hosted in http://zn.stfx.eu/"
|
|
||||||
self currentLink asUrl host = 'ws.stfx.eu' ifFalse: [ ^ self ].
|
|
||||||
self
|
|
||||||
body: (ZnClient new get: self currentLink);
|
|
||||||
tagAs: 'código'.
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #initialization }
|
|
||||||
GrafoscopioTextNode >> initialize [
|
|
||||||
"I create a empty new node"
|
|
||||||
|
|
||||||
super initialize.
|
|
||||||
self body: ''
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioTextNode >> instantiateBody [
|
|
||||||
| widget |
|
|
||||||
widget := super instantiateBody.
|
|
||||||
widget body whenTextChangedDo: [ :arg | self body: arg ].
|
|
||||||
^ widget
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioTextNode >> isEmpty [
|
|
||||||
body ifNil: [ ^ true ] ifNotNil: [ ^ false ]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #operation }
|
|
||||||
GrafoscopioTextNode >> isSavedAfterLastEdition [
|
|
||||||
| root |
|
|
||||||
root := self root.
|
|
||||||
root edited ifNil: [ ^ false ].
|
|
||||||
^ self unsavedNodes isEmpty.
|
|
||||||
"self unsavedNodes isEmpty ifFalse: [ ^ self unsavedNodes inspect ]"
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #testing }
|
|
||||||
GrafoscopioTextNode >> isSelected [
|
|
||||||
self selected ifNil: [ ^ false ].
|
|
||||||
^ self selected.
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #operation }
|
|
||||||
GrafoscopioTextNode >> isTaggedAs: aString [
|
|
||||||
^ self tags includes: aString
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #exporting }
|
|
||||||
GrafoscopioTextNode >> itemAsMarkdownInto: aStream [
|
|
||||||
"I export a node with %item in its header as valid Pandoc's markdown
|
|
||||||
and replace all line endings to make them Internet friendly.
|
|
||||||
Maybe I should include the condition about my own header, instead of leaving it to markdownContent..."
|
|
||||||
|
|
||||||
| lines |
|
|
||||||
lines := self body contents asString withInternetLineEndings lines.
|
|
||||||
lines ifEmpty: [ ^ self ].
|
|
||||||
aStream
|
|
||||||
nextPutAll: ' - ';
|
|
||||||
nextPutAll: lines first;
|
|
||||||
lf.
|
|
||||||
lines
|
|
||||||
allButFirstDo: [ :line |
|
|
||||||
aStream
|
|
||||||
nextPutAll: ' ';
|
|
||||||
nextPutAll: line;
|
|
||||||
lf ].
|
|
||||||
aStream nextPutAll: String lf
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioTextNode >> key [
|
|
||||||
"Returns a unique key identifying the receiver in the help system"
|
|
||||||
|
|
||||||
^key
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioTextNode >> key: aUniqueKey [
|
|
||||||
"Sets a unique key identifying the receiver in the help system"
|
|
||||||
|
|
||||||
key := aUniqueKey
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioTextNode >> lastLink [
|
|
||||||
self links ifNil: [ ^ '' ].
|
|
||||||
self links ifEmpty: [ ^ '' ].
|
|
||||||
^ self links last
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioTextNode >> lastNetLink [
|
|
||||||
^ self links detect: [ :l | l asZnUrl ]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioTextNode >> links [
|
|
||||||
"I model local or remote links that are associated to a particular node."
|
|
||||||
^ links ifNil: [ ^ links := OrderedCollection new ]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioTextNode >> links: anObject [
|
|
||||||
self links add: anObject
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #operation }
|
|
||||||
GrafoscopioTextNode >> linksToMarkupFile [
|
|
||||||
"I detect if the links contains any reference to a file ending in '.md' or '.markdown'"
|
|
||||||
self links
|
|
||||||
ifNotNil: [
|
|
||||||
self links
|
|
||||||
detect: [:l | (l endsWithAnyOf: #('.md' '.markdown' '.md.html'))]
|
|
||||||
ifFound: [ ^ true ]
|
|
||||||
ifNone: [^ false]].
|
|
||||||
^ false
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #operation }
|
|
||||||
GrafoscopioTextNode >> localFilesLinks [
|
|
||||||
"I collect all the links that point to the local file system. Because is supposed that
|
|
||||||
links contains only references to remote URL or local files, anything that is not a URL is
|
|
||||||
treated as a loca file link."
|
|
||||||
^ self links collect: [ :l | l asZnUrl host isNil ]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #exporting }
|
|
||||||
GrafoscopioTextNode >> margin [
|
|
||||||
"I define the same margin of the page used for PDF exportations"
|
|
||||||
|
|
||||||
^'2 cm'
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #exporting }
|
|
||||||
GrafoscopioTextNode >> margins [
|
|
||||||
"I define each individual margin of the page used for PDF exportations"
|
|
||||||
|
|
||||||
| margins |
|
|
||||||
margins := Dictionary new
|
|
||||||
add: 'top' -> '3 cm';
|
|
||||||
add: 'bottom' -> '3 cm';
|
|
||||||
add: 'left' -> '2 cm';
|
|
||||||
add: 'right' -> '2 cm';
|
|
||||||
yourself.
|
|
||||||
^ margins
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #exporting }
|
|
||||||
GrafoscopioTextNode >> markdownContent [
|
|
||||||
"I extract 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, that use %keywords in its header or body I convert them
|
|
||||||
into proper markup"
|
|
||||||
| markdownStream |
|
|
||||||
markdownStream := '' writeStream.
|
|
||||||
(self class specialWords includes: self header) not
|
|
||||||
& (self class specialWords includes: ((self header findTokens: $ ) at: 1)) not
|
|
||||||
& (self isTaggedAs: 'código') not
|
|
||||||
& (self hasAncestorHeaderWith: '%invisible') not
|
|
||||||
ifTrue: [
|
|
||||||
self headerAsMarkdownInto: markdownStream.
|
|
||||||
self bodyAsMarkdownInto: markdownStream ].
|
|
||||||
(self headerStartsWith: '%idea')
|
|
||||||
ifTrue: [ self bodyAsMarkdownInto: markdownStream ].
|
|
||||||
(self headerStartsWith: '%item')
|
|
||||||
ifTrue: [ self itemAsMarkdownInto: markdownStream ].
|
|
||||||
(self headerStartsWith: '%footnote')
|
|
||||||
ifTrue: [ self footnoteAsMarkdownInto: markdownStream ].
|
|
||||||
((self isTaggedAs: 'código')
|
|
||||||
and: [(self hasAncestorHeaderWith: '%invisible') not
|
|
||||||
& (self headerStartsWith: '%embed') not ])
|
|
||||||
ifTrue: [ self exportCodeNodeTo: markdownStream ].
|
|
||||||
^ markdownStream contents
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #operation }
|
|
||||||
GrafoscopioTextNode >> metadata [
|
|
||||||
| mnode |
|
|
||||||
mnode := self root preorderTraversal
|
|
||||||
detect: [ :n | n header beginsWith: '%metadata' ]
|
|
||||||
ifNone: [ ^ nil ].
|
|
||||||
^ mnode output.
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #exporting }
|
|
||||||
GrafoscopioTextNode >> metadataAsYamlIn: markdownStream [
|
|
||||||
"I convert the first '%metadata' node into a YAML preamble contents to be used by Pandoc
|
|
||||||
exportation."
|
|
||||||
self metadata
|
|
||||||
ifNil: [ markdownStream nextPutAll: String crlf. ]
|
|
||||||
ifNotNil: [
|
|
||||||
self metadata
|
|
||||||
keysAndValuesDo: [ :k :v |
|
|
||||||
k = 'pandocOptions'
|
|
||||||
ifTrue: [
|
|
||||||
markdownStream
|
|
||||||
nextPutAll:
|
|
||||||
(k, ': ', self pandocOptionsPrettyYaml) ]
|
|
||||||
ifFalse: [
|
|
||||||
markdownStream
|
|
||||||
nextPutAll:
|
|
||||||
(k , ': ' , v asString) withInternetLineEndings;
|
|
||||||
lf] ]].
|
|
||||||
markdownStream
|
|
||||||
nextPutAll: String cr, String cr.
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioTextNode >> openIn: aNotebook [
|
|
||||||
super openIn: aNotebook.
|
|
||||||
aNotebook links text: self lastLink
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioTextNode >> output [
|
|
||||||
(self isTaggedAs: 'código')
|
|
||||||
ifFalse: [ ^ self ].
|
|
||||||
self body ifNil: [ ^ nil ].
|
|
||||||
^ OpalCompiler new
|
|
||||||
source: self body;
|
|
||||||
evaluate
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #utility }
|
|
||||||
GrafoscopioTextNode >> pandocOptions [
|
|
||||||
self metadata ifNil: [ ^ nil ].
|
|
||||||
self metadata at: 'pandocOptions' ifAbsent: [ ^ '' ].
|
|
||||||
^ self metadata at: 'pandocOptions'
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #utility }
|
|
||||||
GrafoscopioTextNode >> pandocOptionsPrettyYaml [
|
|
||||||
"I convert pandoc options, if present into an indented Yaml block."
|
|
||||||
| yamlOutput pretyOutput |
|
|
||||||
pretyOutput := STON toStringPretty: self pandocOptions.
|
|
||||||
yamlOutput := '' writeStream.
|
|
||||||
yamlOutput
|
|
||||||
nextPutAll:
|
|
||||||
'|';
|
|
||||||
lf.
|
|
||||||
pretyOutput linesDo: [ :line |
|
|
||||||
yamlOutput
|
|
||||||
nextPutAll:
|
|
||||||
' ', line;
|
|
||||||
lf ].
|
|
||||||
^ yamlOutput contents
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'add/remove nodes' }
|
|
||||||
GrafoscopioTextNode >> pasteFromClipboard [
|
|
||||||
| clipchild |
|
|
||||||
self class clipboard
|
|
||||||
ifNotNil: [
|
|
||||||
clipchild := self class clipboard.
|
|
||||||
self addNode: clipchild.
|
|
||||||
clipchild ]
|
|
||||||
ifNil: [ self inform: 'Cache is emtpy. Pleas cut/copy a node before pasting' ]
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #operation }
|
|
||||||
GrafoscopioTextNode >> preorderTraversal [
|
|
||||||
| nodesInPreorder |
|
|
||||||
nodesInPreorder := OrderedCollection new.
|
|
||||||
self buildPreorderCollection: nodesInPreorder.
|
|
||||||
^ nodesInPreorder
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #exporting }
|
|
||||||
GrafoscopioTextNode >> publish [
|
|
||||||
| publishedUrl |
|
|
||||||
(self confirm: 'Publish playground content to the cloud?')
|
|
||||||
ifFalse: [ ^ self ].
|
|
||||||
self content ifEmpty: [
|
|
||||||
self inform: 'Nothing was published because the playground is empty'.
|
|
||||||
^ self ].
|
|
||||||
Clipboard clipboardText: (publishedUrl := (GTUrlProvider new post: self content) asString).
|
|
||||||
self inform: publishedUrl , ' was published and the url was copied to clipboard'
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'add/remove nodes' }
|
|
||||||
GrafoscopioTextNode >> 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 : #utility }
|
|
||||||
GrafoscopioTextNode >> removeLeadingLineNumbersSized: anInteger [
|
|
||||||
| cleanBody |
|
|
||||||
cleanBody := ''.
|
|
||||||
self body lines do: [ :line | | cleanLine |
|
|
||||||
line size >= anInteger
|
|
||||||
ifTrue: [ cleanLine := line copyFrom: anInteger to: line size. ]
|
|
||||||
ifFalse: [ cleanLine := '' ].
|
|
||||||
cleanBody := cleanBody, cleanLine, String cr ].
|
|
||||||
self body: cleanBody asString.
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'add/remove nodes' }
|
|
||||||
GrafoscopioTextNode >> removeNode: aNode [
|
|
||||||
(self children includes: aNode)
|
|
||||||
ifTrue: [ self children remove: aNode ]
|
|
||||||
ifFalse: [ self inform: 'The node doesn''t belong to this node children' ]
|
|
||||||
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #utility }
|
|
||||||
GrafoscopioTextNode >> replaceAccentedHTMLChars [
|
|
||||||
self body: (self body copyReplaceAll: 'í' with: 'í' )
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioTextNode >> root [
|
|
||||||
"I return the root node of the Grafoscopio tree, i.e the common ancestor of all other nodes"
|
|
||||||
self level = 0
|
|
||||||
ifFalse: [ ^ self ancestors first ].
|
|
||||||
^ self
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #operation }
|
|
||||||
GrafoscopioTextNode >> sanitizeDefaultLink [
|
|
||||||
| defaultLink sanitized protocol |
|
|
||||||
defaultLink := self lastLink.
|
|
||||||
protocol := 'docutopia://'.
|
|
||||||
sanitized := (defaultLink beginsWith: protocol)
|
|
||||||
ifTrue: [ defaultLink
|
|
||||||
copyReplaceAll: protocol
|
|
||||||
with: 'https://docutopia.tupale.co/' ]
|
|
||||||
ifFalse: [ defaultLink ].
|
|
||||||
^ sanitized
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioTextNode >> saveContent: anObject [
|
|
||||||
"Sets the receivers body to the given object"
|
|
||||||
|
|
||||||
body := anObject
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #operation }
|
|
||||||
GrafoscopioTextNode >> selectMarkupSubtreesToExport [
|
|
||||||
^ (self root preorderTraversal) select: [ :each | each linksToMarkupFile ].
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'as yet unclassified' }
|
|
||||||
GrafoscopioTextNode >> shouldAskBeforeRemove [
|
|
||||||
^ self body isNotEmpty or: [ self hasChildren ]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioTextNode >> specModelClass [
|
|
||||||
"por defecto"
|
|
||||||
|
|
||||||
^ GrafoscopioNewTextModel
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #operation }
|
|
||||||
GrafoscopioTextNode >> subtreeCopy [
|
|
||||||
"I return the same node if its subtree only contains the receiver, or a copy of the receivers
|
|
||||||
subtree, in other cases."
|
|
||||||
| linearSubtree linearSubtreeCopy |
|
|
||||||
linearSubtree := self preorderTraversal.
|
|
||||||
linearSubtreeCopy := OrderedCollection new.
|
|
||||||
linearSubtree do: [ :cn | linearSubtreeCopy add: cn surfaceCopy ].
|
|
||||||
linearSubtreeCopy allButFirst doWithIndex: [ :n :i | | parentPos |
|
|
||||||
parentPos := linearSubtree indexOf: (linearSubtree at: i+1) parent.
|
|
||||||
n parent: (linearSubtreeCopy at: parentPos) ].
|
|
||||||
^ linearSubtreeCopy at: 1.
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #operation }
|
|
||||||
GrafoscopioTextNode >> surfaceCopy [
|
|
||||||
"I copy the most relevant values of the receiver. I'm useful to avoid copying references
|
|
||||||
to the rest of the container tree, which could end in copying the whole tree."
|
|
||||||
| newNode |
|
|
||||||
newNode := self class new.
|
|
||||||
newNode
|
|
||||||
header: self header;
|
|
||||||
body: self body;
|
|
||||||
tags: self tags.
|
|
||||||
self links ifNotEmpty: [ newNode links addAll: self links ].
|
|
||||||
^ newNode.
|
|
||||||
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #operation }
|
|
||||||
GrafoscopioTextNode >> 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 }
|
|
||||||
GrafoscopioTextNode >> unsavedNodes [
|
|
||||||
"I collect all nodes that have changed after the last saving"
|
|
||||||
| lastSavedOn root unsavedNodes |
|
|
||||||
root := self root.
|
|
||||||
lastSavedOn := root edited asDateAndTime.
|
|
||||||
unsavedNodes := root preorderTraversal select: [ :currentNode |
|
|
||||||
currentNode edited isNotNil and: [currentNode edited asDateAndTime > lastSavedOn] ].
|
|
||||||
^ unsavedNodes.
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #importing }
|
|
||||||
GrafoscopioTextNode >> uploadBodyFrom: fileLocator filteredFor: selectedLink [
|
|
||||||
self body: fileLocator contents
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #operation }
|
|
||||||
GrafoscopioTextNode >> visitLastLink [
|
|
||||||
self lastLink = ''
|
|
||||||
ifTrue: [ self inform: 'This node has no associated links to visit'. ^ self ].
|
|
||||||
[WebBrowser openOn: self lastLink] fork
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'as yet unclassified' }
|
|
||||||
GrafoscopioTextNode >> wrapBodyLines [
|
|
||||||
"I convert the node body from HTML format to Pandoc's Markdown."
|
|
||||||
|
|
||||||
self wrapBodyLines: 80
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #'as yet unclassified' }
|
|
||||||
GrafoscopioTextNode >> wrapBodyLines: aWidth [
|
|
||||||
"I convert the node body from HTML format to Pandoc's Markdown."
|
|
||||||
|
|
||||||
| bodyReader chunck |
|
|
||||||
(self isTaggedAs: 'código')
|
|
||||||
ifTrue: [ ^ self ].
|
|
||||||
bodyReader := body readStream.
|
|
||||||
body := String
|
|
||||||
streamContents: [ :bodyWriter |
|
|
||||||
[ bodyReader atEnd ]
|
|
||||||
whileFalse: [
|
|
||||||
chunck := bodyReader next: aWidth - 1.
|
|
||||||
bodyWriter nextPutAll: chunck.
|
|
||||||
bodyReader atEnd
|
|
||||||
ifFalse: [ bodyWriter nextPut: Character lf ] ] ]
|
|
||||||
]
|
]
|
||||||
|
85
repository/Grafoscopio/GrafoscopioTreeNotebook.class.st
Normal file
85
repository/Grafoscopio/GrafoscopioTreeNotebook.class.st
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
Class {
|
||||||
|
#name : #GrafoscopioTreeNotebook,
|
||||||
|
#superclass : #SpPresenter,
|
||||||
|
#instVars : [
|
||||||
|
'#sidebar',
|
||||||
|
'#viewport',
|
||||||
|
'#model',
|
||||||
|
'=>',
|
||||||
|
'SpObservableSlot',
|
||||||
|
'#empty',
|
||||||
|
'#perspectives'
|
||||||
|
],
|
||||||
|
#category : 'Grafoscopio-New-UI'
|
||||||
|
}
|
||||||
|
|
||||||
|
{ #category : #specs }
|
||||||
|
GrafoscopioTreeNotebook class >> defaultSpec [
|
||||||
|
^ SpBoxLayout newHorizontal
|
||||||
|
add:
|
||||||
|
(SpBoxLayout newVertical
|
||||||
|
add: #empty height: self toolbarHeight;
|
||||||
|
add: #sidebar;
|
||||||
|
yourself)
|
||||||
|
width: 51;
|
||||||
|
add: #viewport;
|
||||||
|
yourself
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
GrafoscopioTreeNotebook >> createDefaultComponent [
|
||||||
|
^ GrafoscopioPerspective defaultPerspective new
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
GrafoscopioTreeNotebook >> initialize [
|
||||||
|
super initialize.
|
||||||
|
perspectives := Dictionary new.
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
GrafoscopioTreeNotebook >> initializePrivateAnnouncements [
|
||||||
|
super initializePrivateAnnouncements.
|
||||||
|
self property: #model whenChangedDo: [ self updateModel ]
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
GrafoscopioTreeNotebook >> initializeWidgets [
|
||||||
|
super initializeWidgets.
|
||||||
|
sidebar := self sidebar.
|
||||||
|
viewport := self createDefaultComponent.
|
||||||
|
empty := self newLabel.
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
GrafoscopioTreeNotebook >> installPerspective: aPerspective [
|
||||||
|
viewport ifNotNil: [ viewport aboutToBeUninstalledFrom: self ].
|
||||||
|
viewport := (perspectives at: aPerspective ifAbsentPut: [ self instantiate: aPerspective ]) .
|
||||||
|
self updateModel.
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #'as yet unclassified' }
|
||||||
|
GrafoscopioTreeNotebook >> open: aGrafoscopioProject [
|
||||||
|
model := aGrafoscopioProject.
|
||||||
|
self openWithSpec.
|
||||||
|
self updateModel
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
GrafoscopioTreeNotebook >> sidebar [
|
||||||
|
| bar |
|
||||||
|
bar := self instantiate: SpSidebar.
|
||||||
|
GrafoscopioPerspective perspectives
|
||||||
|
do:
|
||||||
|
[ :p | bar addAction: [ self installPerspective: p ] icon: p icon ].
|
||||||
|
^ bar
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
GrafoscopioTreeNotebook >> updateModel [
|
||||||
|
viewport updateModel: model.
|
||||||
|
|
||||||
|
self needRebuild: false.
|
||||||
|
self buildWithSpec
|
||||||
|
|
||||||
|
]
|
@ -1,50 +0,0 @@
|
|||||||
Class {
|
|
||||||
#name : #GrafoscopioTrunkNode,
|
|
||||||
#superclass : #GrafoscopioAbstractNode,
|
|
||||||
#instVars : [
|
|
||||||
'children'
|
|
||||||
],
|
|
||||||
#category : 'Grafoscopio-Model'
|
|
||||||
}
|
|
||||||
|
|
||||||
{ #category : #testing }
|
|
||||||
GrafoscopioTrunkNode class >> isAbstract [
|
|
||||||
^ self = GrafoscopioTrunkNode
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioTrunkNode >> children [
|
|
||||||
"Returns the receivers list of children"
|
|
||||||
|
|
||||||
^ children ifNil: [ children := OrderedCollection new ]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioTrunkNode >> children: aCollection [
|
|
||||||
"Sets the receivers children"
|
|
||||||
|
|
||||||
aCollection do: [:currentNode | currentNode parent: self ].
|
|
||||||
children := aCollection.
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioTrunkNode >> isLeaf [
|
|
||||||
^ false
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #movement }
|
|
||||||
GrafoscopioTrunkNode >> moveDown: aNode [
|
|
||||||
| index |
|
|
||||||
"Moves the current node a place before in the children collection where is located"
|
|
||||||
index := (children indexOf: aNode) max: 1 .
|
|
||||||
|
|
||||||
children swap: index with: (index + 1 min: children size)
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #movement }
|
|
||||||
GrafoscopioTrunkNode >> moveUp: aNode [
|
|
||||||
| index |
|
|
||||||
"Moves the current node a place before in the children collection where is located"
|
|
||||||
index := children indexOf: aNode.
|
|
||||||
children swap: index with: (index - 1 max: 1)
|
|
||||||
]
|
|
31
repository/Grafoscopio/GrafoscopioUnitNode.class.st
Normal file
31
repository/Grafoscopio/GrafoscopioUnitNode.class.st
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
Class {
|
||||||
|
#name : #GrafoscopioUnitNode,
|
||||||
|
#superclass : #GrafoscopioBranchNode,
|
||||||
|
#category : 'Grafoscopio-Model'
|
||||||
|
}
|
||||||
|
|
||||||
|
{ #category : #'instance creation' }
|
||||||
|
GrafoscopioUnitNode class >> icon [
|
||||||
|
^ self iconNamed: #smallHierarchyBrowser
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #'instance creation' }
|
||||||
|
GrafoscopioUnitNode class >> nameForSelection [
|
||||||
|
^ 'New unit'
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #'instance creation' }
|
||||||
|
GrafoscopioUnitNode class >> showInMenu [
|
||||||
|
^ true
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
GrafoscopioUnitNode >> acceptVisitor: aGrafoscopioVisitor [
|
||||||
|
aGrafoscopioVisitor visitUnitNode: self.
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
GrafoscopioUnitNode >> acceptsChildsOfClass: aClass [
|
||||||
|
^ aClass isLeaf or: [ aClass = self class ]
|
||||||
|
]
|
@ -1,27 +0,0 @@
|
|||||||
Class {
|
|
||||||
#name : #GrafoscopioUrlCachedNode,
|
|
||||||
#superclass : #GrafoscopioUrlNode,
|
|
||||||
#instVars : [
|
|
||||||
'content'
|
|
||||||
],
|
|
||||||
#category : 'Grafoscopio-Model'
|
|
||||||
}
|
|
||||||
|
|
||||||
{ #category : #'instance creation' }
|
|
||||||
GrafoscopioUrlCachedNode class >> nameForSelection [
|
|
||||||
^ 'New URL-Cached Node'
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioUrlCachedNode >> content [
|
|
||||||
^ content isEmptyOrNil
|
|
||||||
ifTrue: [ content := super content ]
|
|
||||||
ifFalse: [ content ]
|
|
||||||
]
|
|
||||||
|
|
||||||
{ #category : #accessing }
|
|
||||||
GrafoscopioUrlCachedNode >> content: aContent [
|
|
||||||
self
|
|
||||||
error:
|
|
||||||
'You are not supposed to change the content of url node from outside. The content comes only from the fetch.'
|
|
||||||
]
|
|
@ -1,12 +1,20 @@
|
|||||||
|
"
|
||||||
|
URL Node downloads content for rendering.
|
||||||
|
"
|
||||||
Class {
|
Class {
|
||||||
#name : #GrafoscopioUrlNode,
|
#name : #GrafoscopioUrlNode,
|
||||||
#superclass : #GrafoscopioAbstractNode,
|
#superclass : #GrafoscopioLeafNode,
|
||||||
#instVars : [
|
#instVars : [
|
||||||
'link'
|
'link'
|
||||||
],
|
],
|
||||||
#category : 'Grafoscopio-Model'
|
#category : 'Grafoscopio-Model'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{ #category : #'instance creation' }
|
||||||
|
GrafoscopioUrlNode class >> icon [
|
||||||
|
^ self iconNamed: #remote
|
||||||
|
]
|
||||||
|
|
||||||
{ #category : #'instance creation' }
|
{ #category : #'instance creation' }
|
||||||
GrafoscopioUrlNode class >> nameForSelection [
|
GrafoscopioUrlNode class >> nameForSelection [
|
||||||
^ 'New URL Node'
|
^ 'New URL Node'
|
||||||
@ -19,6 +27,17 @@ GrafoscopioUrlNode class >> new [
|
|||||||
yourself
|
yourself
|
||||||
]
|
]
|
||||||
|
|
||||||
|
{ #category : #'instance creation' }
|
||||||
|
GrafoscopioUrlNode class >> showInMenu [
|
||||||
|
^ true
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #'as yet unclassified' }
|
||||||
|
GrafoscopioUrlNode >> acceptVisitor: aGrafoscopioVisitor [
|
||||||
|
aGrafoscopioVisitor visitUrlNode: self.
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
{ #category : #'as yet unclassified' }
|
{ #category : #'as yet unclassified' }
|
||||||
GrafoscopioUrlNode >> content [
|
GrafoscopioUrlNode >> content [
|
||||||
^ (self url
|
^ (self url
|
||||||
|
45
repository/Grafoscopio/GrafoscopioViewportVisitor.class.st
Normal file
45
repository/Grafoscopio/GrafoscopioViewportVisitor.class.st
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
Class {
|
||||||
|
#name : #GrafoscopioViewportVisitor,
|
||||||
|
#superclass : #GrafoscopioVisitor,
|
||||||
|
#instVars : [
|
||||||
|
'viewport',
|
||||||
|
'stack',
|
||||||
|
'items',
|
||||||
|
'presenter'
|
||||||
|
],
|
||||||
|
#category : 'Grafoscopio-New-UI'
|
||||||
|
}
|
||||||
|
|
||||||
|
{ #category : #visiting }
|
||||||
|
GrafoscopioViewportVisitor >> createViewportFor: aDocumentNode into: aPresenter [
|
||||||
|
presenter := aPresenter.
|
||||||
|
items := OrderedCollection new.
|
||||||
|
aDocumentNode acceptVisitor: self.
|
||||||
|
viewport := aPresenter instantiate: SpComponentListPresenter.
|
||||||
|
viewport items: items.
|
||||||
|
^ viewport
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #visiting }
|
||||||
|
GrafoscopioViewportVisitor >> visitCodeNode: aNode [
|
||||||
|
| code |
|
||||||
|
code := presenter newCode.
|
||||||
|
code text: aNode text.
|
||||||
|
items add: code.
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #visiting }
|
||||||
|
GrafoscopioViewportVisitor >> visitTextNode: aNode [
|
||||||
|
| text |
|
||||||
|
text := presenter newText .
|
||||||
|
text text: aNode text.
|
||||||
|
items add: text.
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #visiting }
|
||||||
|
GrafoscopioViewportVisitor >> visitUrlNode: aNode [
|
||||||
|
| text |
|
||||||
|
text := presenter newText .
|
||||||
|
text text: aNode content.
|
||||||
|
items add: text.
|
||||||
|
]
|
48
repository/Grafoscopio/GrafoscopioVisitor.class.st
Normal file
48
repository/Grafoscopio/GrafoscopioVisitor.class.st
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
Class {
|
||||||
|
#name : #GrafoscopioVisitor,
|
||||||
|
#superclass : #Object,
|
||||||
|
#category : 'Grafoscopio-Model'
|
||||||
|
}
|
||||||
|
|
||||||
|
{ #category : #visiting }
|
||||||
|
GrafoscopioVisitor >> visitBranchNode: aNode [
|
||||||
|
self visitNode: aNode.
|
||||||
|
aNode children do: [ : c | c acceptVisitor: self ].
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #visiting }
|
||||||
|
GrafoscopioVisitor >> visitCodeNode: aNode [
|
||||||
|
self visitNode: aNode
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #visiting }
|
||||||
|
GrafoscopioVisitor >> visitLeafNode: aNode [
|
||||||
|
self visitNode: aNode
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #visiting }
|
||||||
|
GrafoscopioVisitor >> visitNode: aNode [
|
||||||
|
" nothing to do here"
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #visiting }
|
||||||
|
GrafoscopioVisitor >> visitRootNode: aNode [
|
||||||
|
self visitNode: aNode.
|
||||||
|
aNode children do: [ : c | c acceptVisitor: self ].
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #visiting }
|
||||||
|
GrafoscopioVisitor >> visitTextNode: aNode [
|
||||||
|
self visitNode: aNode
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #visiting }
|
||||||
|
GrafoscopioVisitor >> visitUnitNode: aNode [
|
||||||
|
self visitNode: aNode.
|
||||||
|
aNode children do: [ : c | c acceptVisitor: self ].
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #visiting }
|
||||||
|
GrafoscopioVisitor >> visitUrlNode: aNode [
|
||||||
|
self visitNode: aNode
|
||||||
|
]
|
@ -0,0 +1,15 @@
|
|||||||
|
Class {
|
||||||
|
#name : #GrafoscopioZoaPediaPerspective,
|
||||||
|
#superclass : #GrafoscopioPerspective,
|
||||||
|
#category : 'Grafoscopio-New-UI'
|
||||||
|
}
|
||||||
|
|
||||||
|
{ #category : #accessing }
|
||||||
|
GrafoscopioZoaPediaPerspective class >> icon [
|
||||||
|
^ self iconNamed: #edit
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
GrafoscopioZoaPediaPerspective >> createViewport [
|
||||||
|
^ self newLabel
|
||||||
|
]
|
44
repository/Grafoscopio/SpSidebar.class.st
Normal file
44
repository/Grafoscopio/SpSidebar.class.st
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
Class {
|
||||||
|
#name : #SpSidebar,
|
||||||
|
#superclass : #SpPresenter,
|
||||||
|
#instVars : [
|
||||||
|
'container'
|
||||||
|
],
|
||||||
|
#category : 'Grafoscopio-New-UI'
|
||||||
|
}
|
||||||
|
|
||||||
|
{ #category : #specs }
|
||||||
|
SpSidebar class >> defaultSpec [
|
||||||
|
^ SpBoxLayout newHorizontal
|
||||||
|
add: #container ;
|
||||||
|
yourself
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
SpSidebar >> addAction: aBlock icon: anIcon [
|
||||||
|
container
|
||||||
|
addPresenter:
|
||||||
|
(self createDefaultPresenter
|
||||||
|
parent: self;
|
||||||
|
action: [ :state |
|
||||||
|
container unselectAll.
|
||||||
|
aBlock cull: state ];
|
||||||
|
icon: anIcon;
|
||||||
|
yourself)
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #'as yet unclassified' }
|
||||||
|
SpSidebar >> buttons [
|
||||||
|
^ container items
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
SpSidebar >> createDefaultPresenter [
|
||||||
|
^ self instantiate: SpSquareButton.
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
SpSidebar >> initializeWidgets [
|
||||||
|
super initializeWidgets.
|
||||||
|
container := self instantiate: SpComponentListPresenter.
|
||||||
|
]
|
52
repository/Grafoscopio/SpSquareButton.class.st
Normal file
52
repository/Grafoscopio/SpSquareButton.class.st
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
Class {
|
||||||
|
#name : #SpSquareButton,
|
||||||
|
#superclass : #SpPresenter,
|
||||||
|
#instVars : [
|
||||||
|
'button',
|
||||||
|
'parent'
|
||||||
|
],
|
||||||
|
#category : 'Grafoscopio-New-UI'
|
||||||
|
}
|
||||||
|
|
||||||
|
{ #category : #specs }
|
||||||
|
SpSquareButton class >> defaultSpec [
|
||||||
|
^ SpBoxLayout newVertical
|
||||||
|
add: (SpBoxLayout newHorizontal add: #button width: 50; yourself) height: 50;
|
||||||
|
yourself
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
SpSquareButton >> action: anAction [
|
||||||
|
button
|
||||||
|
action: [ :state |
|
||||||
|
state
|
||||||
|
ifTrue: [ parent buttons
|
||||||
|
reject: [ :b | b = self ]
|
||||||
|
thenDo: [ :b | b toggleOff ].
|
||||||
|
anAction cull: state ]
|
||||||
|
ifFalse: [ ] ]
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
SpSquareButton >> icon: icon [
|
||||||
|
button icon: icon
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
SpSquareButton >> initializeWidgets [
|
||||||
|
super initializeWidgets.
|
||||||
|
button := self newToggleButton
|
||||||
|
extent: 90 @ 50;
|
||||||
|
color: Color transparent;
|
||||||
|
yourself
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #'as yet unclassified' }
|
||||||
|
SpSquareButton >> parent: aSpSidebar [
|
||||||
|
parent := aSpSidebar
|
||||||
|
]
|
||||||
|
|
||||||
|
{ #category : #initialization }
|
||||||
|
SpSquareButton >> toggleOff [
|
||||||
|
button state: false.
|
||||||
|
]
|
Loading…
Reference in New Issue
Block a user