MultiViewToolApplication.st
author Claus Gittinger <cg@exept.de>
Wed, 09 Aug 2006 14:48:41 +0200
changeset 6863 4e2e267622eb
parent 6634 a94d8a07247d
child 7475 54b889153fc7
permissions -rw-r--r--
*** empty log message ***

"
 COPYRIGHT (c) 2004 by eXept Software AG
              All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"

"{ Package: 'stx:libtool' }"

ToolApplicationModel subclass:#MultiViewToolApplication
	instanceVariableNames:'workspaces tabList selectedWorkspaceIndexHolder workspaceHolder'
	classVariableNames:''
	poolDictionaries:''
	category:'Interface-Smalltalk'
!

!MultiViewToolApplication class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 2004 by eXept Software AG
              All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"
!

documentation
"
    Common code for multiView applications (Workspace and Terminal app)

    [author:]
        Claus Gittinger
"
! !

!MultiViewToolApplication class methodsFor:'interface specs'!

windowSpec
    "raise an error: must be redefined in concrete subclass(es)"

    ^ self subclassResponsibility
! !

!MultiViewToolApplication class methodsFor:'menu specs'!

mainMenu
    "raise an error: must be redefined in concrete subclass(es)"

    ^ self subclassResponsibility
!

tabMenu
    "raise an error: must be redefined in concrete subclass(es)"

    ^ self subclassResponsibility
! !

!MultiViewToolApplication class methodsFor:'queries'!

isVisualStartable
    "return true, if this application can be started via #open.
     (to allow start of a change browser via double-click in the browser)"

    self == MultiViewToolApplication ifTrue:[^false].
    ^ super isVisualStartable
! !

!MultiViewToolApplication methodsFor:'accessing'!

selectedWorkspace
    |wsIndex|

    workspaces isNil ifTrue:[
        workspaces := OrderedCollection new.
    ].
    wsIndex := self selectedWorkspaceIndexHolder value.
    wsIndex == 0 ifTrue:[
        ^ nil
    ].

    workspaces size < wsIndex ifTrue:[
        workspaces grow:wsIndex.
        workspaces at:wsIndex put:(self createWorkspace).
    ].
    ^ workspaces at:wsIndex
!

tabMenuAt:index
    <resource: #programMenu>

    |m i ws|

    m := self class tabMenu.
    m := m decodeAsLiteralArray.
    i := m detectItem:[:item | item value == #removeWorkspace:] ifNone:nil.
    i notNil ifTrue:[
        i argument:index.
        index ~~ self selectedWorkspaceIndexHolder value ifTrue:[
            "/ for now: if that buffer is modified,
            "/ do not allow removing.
            "/ (must be brought to front, in order for check-for-modification to work)
            ws := workspaces at:index.
            (ws isKindOf:ScrollableView) ifTrue:[
                ws := ws scrolledView
            ].
            ((ws isKindOf:TextView) not
            or:[ ws modified ])
            ifTrue:[
                i disable
            ].
        ].
    ].
    i := m detectItem:[:item | item value == #renameWorkspace:] ifNone:nil.
    i notNil ifTrue:[
        i argument:index.
    ].

    m findGuiResourcesIn:self.
    ^ m
!

workspaceHolder
    workspaceHolder isNil ifTrue:[
        workspaceHolder := ValueHolder with:(self selectedWorkspace).
    ].
    ^ workspaceHolder
! !

!MultiViewToolApplication methodsFor:'aspects'!

selectedWorkspaceIndexHolder
    selectedWorkspaceIndexHolder isNil ifTrue:[
        selectedWorkspaceIndexHolder := 1 asValue.
        selectedWorkspaceIndexHolder onChangeSend:#workspaceSelectionChanged to:self.
    ].
    ^ selectedWorkspaceIndexHolder.
!

tabList
    tabList isNil ifTrue:[
        tabList := List new.
    ].
    ^ tabList.
! !

!MultiViewToolApplication methodsFor:'aspects-queries'!

canRemoveWorkspace
    ^ self canRemoveWorkspace:(self selectedWorkspaceIndexHolder value)
!

canRemoveWorkspace:idx
    ^ self tabList size > 1
"/       and:[ (self workspacesTextViewAt:(self selectedWorkspaceIndexHolder value))
!

hasMultipleBuffersHolder
    ^ [ workspaces size > 1 ]
!

hasSelectionInActiveWorkspace
    |v|

    v := self selectedWorkspacesTextView.
    ^ v notNil and:[v selectionAsString size > 0]
! !

!MultiViewToolApplication methodsFor:'menu-actions'!

addWindow:aWindow named:name
    ^ self addWindow:aWindow named:name asFirst:false
!

addWindow:aWindow named:name asFirst:asFirst
    |tabList wsIndex newSelectedIndex|

    tabList := self tabList.
    wsIndex := tabList size + 1.
    wsIndex == 1 ifTrue:[
        "/ first - add a name for the first tab
        tabList add:(self window label). "/ 'Workspace'.
        wsIndex := wsIndex + 1.
    ].

    workspaces grow:wsIndex.
    asFirst ifTrue:[
        tabList addFirst:(name bindWith:wsIndex).
        workspaces replaceFrom:2 to:wsIndex with:workspaces startingAt:1.
        newSelectedIndex := 1.
    ] ifFalse:[
        tabList addLast:(name bindWith:wsIndex).
        newSelectedIndex := wsIndex.
    ].
    workspaces at:newSelectedIndex put:aWindow.
    self selectedWorkspaceIndexHolder value:newSelectedIndex.   
"/    workspaceHolder value:aWindow.
!

defaultFileNameForSave
    ^ 'file.wsp'
!

defaultFileNameForSaveAll
   ^ 'file.wsp'
!

destroyTab:tabIndex
    self removeWorkspace:tabIndex
!

menuSaveAllAs
    self 
        askForFile:'Save all Buffers into:' 
        default:(self defaultFilenameForSaveAll)
        thenDo:[:file :doAppend |
            |ws append|

            append := doAppend.
            workspaces do:[:subView |
                |ws|

                ws := self workspaceViewOfView:subView.
                ws notNil ifTrue:[
                    ws saveAs:file doAppend:append.
                    ws modified:false.
                ].
                append := true.
            ].
        ]
!

menuSaveAs
    self 
        askForFile:'Save Buffer into:'
        default:(self defaultFileNameForSave)
        thenDo:[:file :doAppend |
            |ws|

            ws := self selectedWorkspacesTextView.
            ws saveAs:file doAppend:doAppend.
            ws modified:false.
        ]
!

newWorkspace
    self class new openWithExtent:(self builder window extent).
!

removeWorkspace
    self removeWorkspace:(self selectedWorkspaceIndexHolder value)
!

removeWorkspace:wsIndex
    |tabList newWsIndex|

    wsIndex == self selectedWorkspaceIndexHolder value ifTrue:[
        (self askIfModified:'Text was modified. Remove buffer anyway ?' yesButton:'Remove Buffer') ifFalse:[
            ^ self
        ].
    ].

    tabList := self tabList.

    wsIndex == tabList size ifTrue:[
        newWsIndex := wsIndex - 1.
    ] ifFalse:[
        newWsIndex := wsIndex.
    ].

    tabList removeIndex:wsIndex.
    (workspaces at:wsIndex) destroy.
    workspaces removeIndex:wsIndex.

    tabList size == 1 ifTrue:[
        self window label:(tabList at:1).
        tabList removeIndex:1
    ].

    workspaceHolder value:(workspaces at:newWsIndex).
    self selectedWorkspaceIndexHolder value:newWsIndex.
    "/ to force change (update workspaceHolder - even if same index)
    self selectedWorkspaceIndexHolder changed:#value.   
!

renameWorkspace
    self renameWorkspace:(self selectedWorkspaceIndexHolder value)
!

renameWorkspace:wsIndex
    |tabList oldName newName|

    tabList := self tabList.
    tabList isEmpty ifTrue:[
        oldName := self window label
    ] ifFalse:[
        oldName := tabList at:wsIndex.
    ].
    newName := Dialog request:(resources string:'New Name for %1:' with:oldName) initialAnswer:oldName.
    newName size == 0 ifTrue:[ ^ self].

    self renameWorkspace:wsIndex to:newName.
!

renameWorkspace:wsIndex to:newName
    |tabList|

    tabList := self tabList.
    tabList notEmpty ifTrue:[
        tabList at:wsIndex put:newName.
    ].
    wsIndex == self selectedWorkspaceIndexHolder value ifTrue:[
        self window label:newName.
    ].
! !

!MultiViewToolApplication methodsFor:'menu-actions-editing'!

copySelection
    self selectedWorkspacesTextView copySelection
!

cutSelection
    self selectedWorkspacesTextView cutSelection
!

paste
    self selectedWorkspacesTextView paste
!

paste:aString
    self selectedWorkspacesTextView paste:aString.
!

selectAll
    self selectedWorkspacesTextView selectAll.
! !

!MultiViewToolApplication methodsFor:'private'!

askForFile:question default:defaultFilename thenDo:aBlock
    Dialog
        requestSaveFileName:(resources string:question) 
        default:defaultFilename 
        fromDirectory:nil 
        action:[:fileName | aBlock value:fileName value:false] 
        appendAction:[:fileName | aBlock value:fileName value:true]

"/    |file doAppend|
"/
"/    doAppend := false.
"/    Dialog aboutToOpenBoxNotificationSignal handle:[:n |
"/        |box|
"/
"/        box := n parameter.
"/        box addButton:(Button label:'Append' action:[doAppend := true. box okPressed]).
"/        n proceed.
"/    ] do:[
"/        file := Dialog requestFileName:question default:'file.wsp'. 
"/    ].
"/    file isEmptyOrNil ifFalse:[
"/        aBlock value:file value:doAppend
"/    ].
!

askForFile:question thenDo:aBlock
    ^ self
        askForFile:question default:'file.wsp' thenDo:aBlock
!

askIfAnyModified:arg1 yesButton:arg2 
    "raise an error: must be redefined in concrete subclass(es)"

    ^ self subclassResponsibility
!

askIfModified:question yesButton:yesButtonText
    "tell user, that code has been modified - let her confirm"

    |textView|

    textView := self selectedWorkspace.
    (self isModifiedWorkspace:textView) ifFalse:[^ true].

    (Dialog 
        confirm:(resources stringWithCRs:question)
        yesLabel:(resources string:yesButtonText)
        noLabel:(resources string:'Cancel'))
    ifTrue:[
        "/ reset modified flag so question is asked only once
        textView modified:false.
        ^ true
    ].
    ^ false

    "Modified: 2.10.1997 / 14:23:47 / stefan"
!

createWorkspace
    "raise an error: must be redefined in concrete subclass(es)"

    ^ self subclassResponsibility
!

isModifiedWorkspace:aView
    self subclassResponsibility
!

selectedWorkspacesTextView
    ^ self workspaceViewOfView:(self selectedWorkspace)
!

workspaceSelectionChanged
    |wsIndex windowLabel v|

    "/ self selected
    self workspaceHolder value:(v := self selectedWorkspace).
    wsIndex := self selectedWorkspaceIndexHolder value.

    wsIndex ~~ 0 ifTrue:[
        windowLabel := tabList at:wsIndex ifAbsent:nil.
        windowLabel notNil ifTrue:[self window label:windowLabel].
    ].
!

workspaceViewOfView:aView
    |view|

    view := aView.
    (view isScrollWrapper) ifTrue:[
        view := view scrolledView.
        view isNil ifTrue:[^ nil].
    ].
    (view isTextView) ifFalse:[
        (view isKindOf:InspectorView) ifFalse:[
            ^ nil
        ].
        view := view workspace.
        (view isScrollWrapper) ifTrue:[
            view := view scrolledView
        ].
    ].
    (view isTextView) ifFalse:[
        ^ nil
    ].
    ^ view
! !

!MultiViewToolApplication class methodsFor:'documentation'!

version
    ^ '$Header: /cvs/stx/stx/libtool/MultiViewToolApplication.st,v 1.11 2006-08-09 12:48:41 cg Exp $'
! !