Added support for showing/hiding options panel, but does not work yet.
"{ Package: 'jv:smallsense' }"
"{ NameSpace: SmallSense }"
AbstractDIalog subclass:#AbstractSearchDialog
instanceVariableNames:'matchingObjects matchingObjectsView matchingObjectsTree
matchingObjectsSelectionHolder matchingObjectsLabelHolder
matchingObjectsUpdateJob matchPatternHolder matchPatternView
environmentHolder filterHolder filter recentlySearchedPatterns
recentlySearchedObjects'
classVariableNames:''
poolDictionaries:''
category:'SmallSense-Core-Interface-Search'
!
AbstractSearchDialog class instanceVariableNames:'recentlySearchedPatterns recentlySearchedObjects'
"
The following class instance variables are inherited by this class:
SmallSense::AbstractDIalog -
SimpleDialog -
ApplicationModel - ClassResources
Model -
Object -
"
!
!AbstractSearchDialog class methodsFor:'accessing'!
recentlySearchedObjects
recentlySearchedObjects isNil ifTrue:[
recentlySearchedObjects := OrderedSet new.
].
^ recentlySearchedObjects
"Created: / 28-04-2014 / 23:13:34 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
recentlySearchedPatterns
recentlySearchedPatterns isNil ifTrue:[
recentlySearchedPatterns := OrderedSet new.
].
^ recentlySearchedPatterns
"Created: / 28-04-2014 / 23:13:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!AbstractSearchDialog class methodsFor:'interface specs-content'!
contentPaneSpec
"This resource specification was automatically generated
by the UIPainter of ST/X."
"Do not manually edit this!! If it is corrupted,
the UIPainter may not be able to read the specification."
"
UIPainter new openOnClass:SmallSense::AbstractSearchDialog andSelector:#contentPaneSpec
SmallSense::AbstractSearchDialog new openInterface:#contentPaneSpec
"
<resource: #canvas>
^
#(FullSpec
name: contentPaneSpec
window:
(WindowSpec
label: 'Search...'
name: 'Search...'
min: (Point 10 10)
bounds: (Rectangle 0 0 708 404)
menu: mainMenuSpec
)
component:
(SpecCollection
collection: (
(VerticalPanelViewSpec
name: 'Content'
layout: (LayoutFrame 0 0 0 0 0 1 0 1)
horizontalLayout: fit
verticalLayout: topSpaceFit
component:
(SpecCollection
collection: (
(LabelSpec
label: 'Enter name prefix or pattern (*):'
name: 'PatternLabel'
translateLabel: true
adjust: left
extent: (Point 708 30)
)
(InputFieldSpec
name: 'Pattern'
model: matchPatternHolder
immediateAccept: true
acceptOnReturn: true
acceptOnTab: true
acceptOnPointerLeave: true
entryCompletionBlock: matchPatternCompletionBlock
extent: (Point 706 25)
postBuildCallback: postBuildMatchPatternView:
usePreferredHeight: true
)
(LabelSpec
label: 'Matching items:'
name: 'MatchingLabel'
translateLabel: true
labelChannel: matchingObjectsLabelHolder
adjust: left
extent: (Point 708 25)
)
(HierarchicalListViewSpec
name: 'HierarchicalListView1'
model: matchingObjectsSelectionHolder
hasHorizontalScrollBar: true
hasVerticalScrollBar: true
listModel: matchingObjectsTree
multipleSelectOk: true
useIndex: false
highlightMode: line
doubleClickSelector: doAcceptByDoubleClick
selectConditionSelector: canSelect:
showLines: false
showIndicators: false
showLeftIndicators: false
useDefaultIcons: false
showRoot: false
extent: (Point 708 302)
postBuildCallback: postBuildMatchingObjectsView:
)
)
)
)
)
)
)
! !
!AbstractSearchDialog class methodsFor:'queries'!
isAbstract
"Return if this class is an abstract class.
True is returned here for myself only; false for subclasses.
Abstract subclasses must redefine again."
^ self == SmallSense::AbstractSearchDialog.
! !
!AbstractSearchDialog methodsFor:'accessing'!
environment
^ self environmentHolder value
"Created: / 22-04-2014 / 10:45:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
environment: aJavaClassEnvironment
^self environmentHolder value: aJavaClassEnvironment
"Created: / 22-04-2014 / 10:46:08 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
filter
^self filterHolder value.
"Created: / 11-03-2013 / 17:37:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
lastMatchPattern
^ self class lastMatchPattern
"Created: / 28-04-2014 / 00:08:06 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
lastMatchPattern: aString
self class lastMatchPattern: aString
"Created: / 28-04-2014 / 00:08:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
pattern
^self matchPatternHolder value.
"Created: / 11-03-2013 / 14:39:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
pattern: aString
^self matchPatternHolder value: aString
"Created: / 11-03-2013 / 15:21:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
recentlySearchedObjects
^ recentlySearchedObjects
!
recentlySearchedObjects:aCollection
recentlySearchedObjects := aCollection.
!
recentlySearchedPatterns
^ recentlySearchedPatterns
!
recentlySearchedPatterns:aCollection
recentlySearchedPatterns := aCollection.
! !
!AbstractSearchDialog methodsFor:'aspects'!
environmentHolder
"return/create the 'registryHolder' value holder (automatically generated)"
environmentHolder isNil ifTrue:[
environmentHolder := Smalltalk asValue.
environmentHolder addDependent:self.
].
^ environmentHolder
"Created: / 22-04-2014 / 10:45:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 28-04-2014 / 00:04:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
environmentHolder:something
"set the 'registryHolder' value holder (automatically generated)"
|oldValue newValue|
environmentHolder notNil ifTrue:[
oldValue := environmentHolder value.
environmentHolder removeDependent:self.
].
environmentHolder := something.
environmentHolder notNil ifTrue:[
environmentHolder addDependent:self.
].
newValue := environmentHolder value.
oldValue ~~ newValue ifTrue:[
self update:#value with:newValue from:environmentHolder.
].
"Created: / 22-04-2014 / 10:45:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
filterHolder
"return/create the 'filterHolder' value holder (automatically generated)"
filterHolder isNil ifTrue:[
filterHolder := ValueHolder new.
filterHolder addDependent:self.
].
^ filterHolder
!
filterHolder:something
"set the 'filterHolder' value holder (automatically generated)"
|oldValue newValue|
filterHolder notNil ifTrue:[
oldValue := filterHolder value.
filterHolder removeDependent:self.
].
filterHolder := something.
filterHolder notNil ifTrue:[
filterHolder addDependent:self.
].
newValue := filterHolder value.
oldValue ~~ newValue ifTrue:[
self update:#value with:newValue from:filterHolder.
].
!
matchPatternCompletionBlock
^ self subclassResponsibility
"Created: / 28-04-2014 / 22:30:06 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
matchPatternHolder
<resource: #uiAspect>
matchPatternHolder isNil ifTrue:[
matchPatternHolder := ValueHolder new.
matchPatternHolder addDependent:self.
].
^ matchPatternHolder.
"Modified: / 08-03-2013 / 13:00:04 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified (format): / 08-03-2013 / 14:05:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
matchingObjectsLabelHolder
<resource: #uiAspect>
"automatically generated by UIPainter ..."
"*** the code below creates a default model when invoked."
"*** (which may not be the one you wanted)"
"*** Please change as required and accept it in the browser."
"*** (and replace this comment by something more useful ;-)"
matchingObjectsLabelHolder isNil ifTrue:[
matchingObjectsLabelHolder := ValueHolder with:(resources string:'Matching items:').
"/ if your app needs to be notified of changes, uncomment one of the lines below:
"/ matchingLabelHolder addDependent:self.
"/ matchingLabelHolder onChangeSend:#matchingLabelHolderChanged to:self.
].
^ matchingObjectsLabelHolder.
"Created: / 28-04-2014 / 22:29:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
matchingObjectsSelectionHolder
"return/create the 'matchingClassesSelectionHolder' value holder (automatically generated)"
matchingObjectsSelectionHolder isNil ifTrue:[
matchingObjectsSelectionHolder := ValueHolder new.
matchingObjectsSelectionHolder addDependent:self.
].
^ matchingObjectsSelectionHolder
"Modified: / 08-03-2013 / 14:05:28 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
matchingObjectsSelectionHolder:something
"set the 'matchingClassesSelectionHolder' value holder (automatically generated)"
matchingObjectsSelectionHolder := something.
!
matchingObjectsTree
<resource: #uiAspect>
matchingObjectsTree isNil ifTrue:[
matchingObjectsTree := HierarchicalList new.
matchingObjectsTree showRoot:false.
matchingObjectsTree root:(HierarchicalItem new).
matchingObjectsTree application:self.
self updateNoResults:matchingObjectsTree root.
].
^ matchingObjectsTree.
"Created: / 08-03-2013 / 15:40:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 27-04-2014 / 23:41:52 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!AbstractSearchDialog methodsFor:'aspects-queries'!
hasFilter
^self filterHolder value notNil
"Created: / 08-03-2013 / 15:43:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 11-03-2013 / 17:34:22 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!AbstractSearchDialog methodsFor:'change & update'!
update:something with:aParameter from:changedObject
"Invoked when an object that I depend upon sends a change notification."
"stub code automatically generated - please change as required"
changedObject == matchPatternHolder ifTrue:[
matchingObjectsUpdateJob restart.
^ self.
].
changedObject == matchingObjectsSelectionHolder ifTrue:[
self updateAcceptEnabled.
^ self.
].
changedObject == accept ifTrue:[
accept value ifTrue:[
recentlySearchedPatterns add: self pattern.
acceptedValue := matchingObjectsSelectionHolder value collect:[:e|e subject].
recentlySearchedObjects addAll: acceptedValue.
].
^ self.
].
changedObject == filterHolder ifTrue:[
filter notNil ifTrue:[filter removeDependent: self].
filter := filterHolder value.
filter notNil ifTrue:[filter addDependent: self].
^ self.
] .
changedObject == filter ifTrue:[
matchingObjectsView invalidate.
].
super update:something with:aParameter from:changedObject
"Modified: / 28-04-2014 / 23:17:30 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
updateAcceptEnabled
self acceptEnabledHolder value: matchingObjectsSelectionHolder value notEmptyOrNil.
"Created: / 08-03-2013 / 14:06:38 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 15-03-2013 / 16:23:04 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
updateMatchingLabelToNormal
self matchingObjectsLabelHolder value: (resources string: 'Matching items:').
"Created: / 18-03-2013 / 14:02:52 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 28-04-2014 / 22:29:19 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
updateMatchingLabelToRecentSearches
self matchingObjectsLabelHolder value: (resources string: 'Recently searched:').
"Created: / 30-04-2014 / 11:47:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
updateMatchingLabelToSearching
self matchingObjectsLabelHolder value: (resources string: 'Searching...').
"Created: / 18-03-2013 / 14:01:52 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 28-04-2014 / 22:29:22 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
updateMatchingObjects
| environment |
matchingObjects := nil.
environment := self environment.
self matchPatternHolder value notEmptyOrNil ifTrue:[
| pattern |
pattern := StringPattern fromString: self matchPatternHolder value.
"/ [
"/ self updateMatchingLabelToSearching.
matchingObjects := self matchingObjectsForPattern: pattern inEnvironment: environment.
"/ ] ensure:[
"/ self updateMatchingLabelToNormal.
"/ ]
] ifFalse:[
matchingObjects := self recentlySearchedObjects asArray reversed.
].
self updateMatchingObjects: matchingObjects.
"Created: / 27-04-2014 / 23:48:23 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 30-04-2014 / 11:45:22 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
updateMatchingObjects: objects
| rootPO matchingPOs |
matchingObjects := objects.
matchingPOs := self matchingObjectPOsFor: objects.
rootPO := self matchingObjectsTree root.
rootPO
children:matchingPOs;
expand.
matchingPOs size == 1 ifTrue:[
self matchingObjectsSelectionHolder value:matchingPOs anElement
].
"Created: / 30-04-2014 / 09:53:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
updateNoResults: root
root children:
(Array with: ((HierarchicalItemWithLabel new parent: root; label:((resources string:'No search results...') asText colorizeAllWith: Color gray)))).
root expand.
^self
"Created: / 11-03-2013 / 14:33:50 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 27-04-2014 / 23:42:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!AbstractSearchDialog methodsFor:'event processing'!
keyPressCursorDownInPatternView
matchingObjectsView hasSelection ifFalse:[
matchingObjectsView selectFirst.
] ifTrue:[
matchingObjectsView selectNext.
].
matchingObjectsView windowGroup focusView:matchingObjectsView byTab:true.
"Created: / 22-04-2014 / 11:59:17 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!AbstractSearchDialog methodsFor:'events'!
closeCancel
"cancel was pressed. close the dialog"
accept setValue: nil.
^ super closeCancel.
"Created: / 28-04-2014 / 23:56:01 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!AbstractSearchDialog methodsFor:'forced actions'!
doAcceptByDoubleClick
self acceptEnabledHolder value ifTrue:[
self doAccept
].
"Created: / 08-03-2013 / 14:20:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
doAcceptByReturnKey
self acceptEnabledHolder value ifTrue:[
super doAcceptByReturnKey
].
"Created: / 08-03-2013 / 14:14:49 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!AbstractSearchDialog methodsFor:'hooks'!
commonPostOpen
"/ self updateMatching.
"/ recentlySearchedPatterns notEmptyOrNil ifTrue:[
"/ matchPatternView contents: self recentlySearchedPatterns last.
"/ matchPatternView selectAll.
"/ ].
self recentlySearchedObjects notEmptyOrNil ifTrue:[
self updateMatchingObjects: self recentlySearchedObjects asArray reverse.
self updateMatchingLabelToRecentSearches.
].
self updateAcceptEnabled.
"Created: / 08-03-2013 / 13:15:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 30-04-2014 / 11:48:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
postBuildMatchPatternView:aView
matchPatternView := aView scrolledView.
"/ matchPatternView delegate: self.
matchPatternView onKey:#CursorDown leaveWith:[ self keyPressCursorDownInPatternView ]
"Created: / 28-04-2014 / 22:27:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
postBuildMatchingObjectsView:aView
matchingObjectsView := aView scrolledView.
matchingObjectsView delegate: self.
"Created: / 22-04-2014 / 13:21:17 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!AbstractSearchDialog methodsFor:'initialization'!
initialize
"Invoked when a new instance is created."
super initialize.
"/ please change as required (and remove this comment)
"/ acceptEnabledHolder := nil.
"/ allClassesHolder := nil.
"/ matchingClassesList := nil.
"/ matchingClassesHolder := nil.
"/ matchPatternHolder := nil.
"/ matchingUpdateJob := nil.
self accept addDependent: self.
self matchingObjectsTree. "/force its initialization
matchingObjectsUpdateJob := BackgroundJob named: 'SmallSense search dialog updater' on:[self updateMatchingObjects].
recentlySearchedPatterns := self class recentlySearchedPatterns.
recentlySearchedObjects := self class recentlySearchedObjects.
"Modified: / 28-04-2014 / 23:14:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!AbstractSearchDialog methodsFor:'queries'!
canSelect: selection
"raise an error: must be redefined in concrete subclass(es)"
^ self subclassResponsibility
"Modified (format): / 28-04-2014 / 00:11:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
hasFilterAndClassNamedIsNotYetImported: binaryname
^self hasFilter
and:[masterApplication isNil or:[masterApplication hasFilterAndClassNamedIsNotYetImported: binaryname]]
"Created: / 18-03-2013 / 14:40:49 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
searchingClasses
^self modeHolder value == #classes
"Created: / 11-03-2013 / 14:38:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
searchingMethods
^self modeHolder value == #methods
"Created: / 11-03-2013 / 14:38:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
showOnlyInterfaces
^self showOnlyInterfacesHolder value
"Created: / 18-03-2013 / 10:40:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 18-03-2013 / 13:32:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!AbstractSearchDialog methodsFor:'searching'!
matchingObjectPOsFor: objects
self subclassResponsibility.
"Created: / 30-04-2014 / 09:46:54 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
matchingObjectsForPattern:pattern inEnvironment:environment
self subclassResponsibility
"Created: / 28-04-2014 / 23:20:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !