SmallSense__AbstractSearchDialog.st
author Jan Vrany <jan.vrany@fit.cvut.cz>
Fri, 02 May 2014 10:07:13 +0100
changeset 332 1ea99b9d1a1e
parent 331 eaf776286738
child 333 d0698eecaea4
permissions -rw-r--r--
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>"
! !