////////////////////////////////////////////////////////////////////// // // GETCOL.PRG // // Copyright: // Alaska Software GmbH, (c) 1999. Alle Rechte vorbehalten. // // Inhalt: // Das Beispiel implementiert die XbpGetColumn Klasse, die // XbpGet Objekte zum Editieren einzelner Zellen in einem // XbpBrowse Objekt verwendet. // // Bemerkungen: // // Die folgenden Programmiertechniken werden demonstriert: // // 1. Wie man einen editierbaren Xbase Part in ein Spalten Objekt // einbettet, so daá ein XbpBrowse() basierter Browser editierbar // wird. // // 2. Wie man den Xbase Part entsprechend Browser Anforderungen bewegt. // // 3. Wie man ein XbpGet Objekt in einer Browser Spalte zum Editieren // verwendet. // // 4. Wie man die XbpGetController Klasse ersetzen kann, wenn nur // ein einziges XbpGet Objekt sichtbar ist. // ////////////////////////////////////////////////////////////////////// #pragma Library( "XppUI2.LIB" ) #include "Appevent.ch" #include "Common.ch" #include "Gra.ch" #include "Xbp.ch" CLASS XbpGetColumn FROM XbpColumn PROTECTED: CLASS VAR activeColumn SHARED // Diese Spalte wird gerade editiert VAR xbpGet // Das assoziierte XbpGet Objekt METHOD createXbp // Erzeuge es beim ersten Editieren METHOD setPosAndSize // Bestimme Position und Gr”áe zum Editieren EXPORTED: INLINE METHOD preValidate // Diese Methoden werden von XbpGet Objekten RETURN .T. // w„hrend des Editierens aufgerufen. // Wir fhren im Browser keine Validierung INLINE METHOD postValidate // durch, d.h. dies sind Dummy Methoden, RETURN .T. // die einen logischen Wert liefern mssen. VAR setHome // Muá fr XbpGet Objekte vorhanden sein ** Ueberladene Methoden METHOD init // Objekt initialisieren METHOD create // Systemresourcen anfordern METHOD destroy // Systemresourcen freigeben METHOD resize // Resize must be reflected by XbpGet during edit METHOD hiliteRow // Display the XbpGet during browsing ** Was man zum Editieren braucht VAR active READONLY // Gibt an, ob der Edit Modus aktiv ist VAR browser // XbpBrowse Objekt, in dem sich die Spalte befindet VAR bufferLength // Max. Anzahl Zeichen bei Eingabe VAR editable // (ak) VAR postBlock // (ak) VAR OldFocus // (ak) VAR killInputFocusSLE // (ak) 18.1.04 VAR killer // ak 18.1.2004 METHOD _LbDown // LbDown Methode fr :dataArea Objekt METHOD read // Editieren beginnt METHOD keyBoard // Wird vom XbpGet Objekt bei UP / DOWN Tasten gerufen METHOD killRead // Editieren endet METHOD activeGet // ak 15.01.2006: Editier-XbpGet abfragen ENDCLASS /* * Objekt initialisieren */ METHOD XbpGetColumn:init( oParent, oOwner, aPos, aSize, aPP, lVisible ) ::xbpColumn:init( oParent, oOwner, aPos, aSize, aPP, lVisible ) ::active := .F. ::setHome := .T. IF oParent <> NIL .AND. oParent:isDerivedFrom( "XbpBrowse" ) ::browser := oParent ENDIF RETURN self /* * Systemresourcen anfordern */ METHOD XbpGetColumn:create( oParent, oOwner, aPos, aSize, aPP, lVisible ) LOCAL oError ::xbpColumn:create( oParent, oOwner, aPos, aSize, aPP, lVisible ) /* * Setze den Fokus zurck auf den Browser wenn die Spalte den Eingabefokus * bekommen soll. Dadurch werden Tastaturereignisse immer vom Browser * verarbeitet. */ ::dataArea:lbDown := {|aPos| ::_lbDown( aPos ) } // ::setInputFocus := {|x,y,obj| SetAppFocus( obj:browser ) } // verschoben nach unten: (ak) IF ::browser == NIL /* * Finde das XbpBrowse Objekt in der Parent-Child Hierarchie * * HINWEIS: Diese DO WHILE Schleife zeigt, wie man die * Parent-Child Hierarchie nach oben durchsucht. * Der Anfang des Parent-Child Baums ist erreicht, * wenn der Parent == AppDesktop() ist. */ oParent := ::setParent() DO WHILE .NOT. oParent:isDerivedFrom( "XbpBrowse" ) oParent := oParent:setParent() IF oParent == AppDesktop() oError := Error():new() oError:description := "Illegal parent defined for " + ::className() oError:operation := ProcName() oError:args := { ::setParent() } Eval( ErrorBlock(), oError ) ENDIF ENDDO /* * Ein XbpBrowse-Objekt wurde in der Parent-Child Hierarchie gefunden */ ::browser := oParent ENDIF ::OldFocus := ::browser //(ak) ::setInputFocus := {|x,y,obj| SetAppFocus( ::OldFocus ) } //(ak) ::killInputFocus := {|x,y,obj| ::OldFocus := SetAppFocus() } //(ak) RETURN self /* * Resourcen freigeben und Objektreferenzen auf NIL setzen. */ METHOD XbpGetColumn:destroy() IF ::xbpGet <> NIL ::xbpGet:controller := NIL ::xbpGet:destroy() ::xbpGet := NIL ENDIF ::active := .F. ::browser := NIL ::XbpColumn:destroy() RETURN self /* * Erzeuge das XbpGet Objekt und weise den :dataLink Codeblock zu */ METHOD XbpGetColumn:createXbp LOCAL aPP := { { XBP_PP_FGCLR , GRA_CLR_BLACK } , ; { XBP_PP_BGCLR , GRA_CLR_YELLOW } } // ak: 21.11.02 ::xbpGet := XbpGet():new( ::dataArea, ::dataArea, NIL, NIL, aPP, .F. ) ::xbpGet:controller := self ::xbpGet:dataLink := ::dataLink IF ::editable <> NIL // a.k. ::xbpGet:editable := ::editable ENDIF IF ::bufferLength <> NIL ::xbpGet:bufferLength := ::bufferLength ENDIF IF ::postBlock <> NIL // a.k. ::xbpGet:postBlock := ::postBlock ENDIF IF ::cargo <> NIL // a.k. 25.8.03 ::xbpGet:cargo := ::cargo ENDIF IF ::killInputFocusSLE <> NIL // ak 18.1.04 ::xbpGet:lIgnoreKillFocus := .T. ::xbpGet:killInputFocus := ::killInputFocusSLE ENDIF IF Upper(AppName()) != "WERNERX.EXE" //+13.11.2012 16:13 ::xbpGet:lbDblClick := ; {| MP1, uNIL, o| clickcalc(o)} // Referenz auf o wrde Wert zurckgeben k”nnen... ENDIF ::xbpGet:create() RETURN /* * X/Y Koordinaten fr die Anzeige von XbpGet ermitteln. */ METHOD XbpGetColumn:setPosAndSize( nRowPos ) LOCAL aRect, aPos, aSize aRect := ::dataArea:cellRect( nRowPos ) aPos := { aRect[1], aRect[2] } aSize := { aRect[3]-aRect[1], aRect[4]-aRect[2] } ::xbpGet:setPos ( aPos ) ::xbpGet:setSize( aSize ) RETURN self /* * Wenn die Spaltenbreite w„hrend des Editierens ge„ndert wird, * muá das XbpGet Objekt die gleiche Breite bekommen. */ METHOD XbpGetColumn:resize( aOldSize, aNewSize ) IF .NOT. ::active RETURN ::xbpColumn:resize( aOldSize, aNewSize ) ENDIF ::xbpGet:hide() ::xbpColumn:resize( aOldSize, aNewSize ) ::setPosAndSize( ::browser:rowPos ) ::xbpGet:show() SetAppFocus( ::xbpGet ) RETURN self /* * Diese Methode wird vom XbpBrowse Objekt aufgerufen, wenn der Browse * Cursor bewegt wird. Sie muá bei editierbaren Spalten das eigentliche * editierbare Objekt auf dem Browse Cursor positionieren. */ METHOD XbpGetColumn:hiliteRow( nRowPos, lHilite, lFrame, lRepaint ) IF ::active IF lHilite /* * Wir befinden uns im Editiermodus und der Browser m”chte seinen * Cursor in hervorgehobener Farbe anzeigen. * Editieren kann fortgesetzt werden. */ ::read( nRowPos ) ELSE /* * Wir befinden uns im Editiermodus und der Browser m”chte seinen * Cursor in normaler Farbe anzeigen. Evaluiere den :dataLink * Codeblock falls etwas ge„ndert wurde und "verstecke" XbpGet. */ IF ::xbpGet <> NIL IF ::xbpGet:changed ::xbpget:vorigerWert := ::xbpGet:original // ak 22.3.04 ::xbpGet:getData() IF ValType(::killer) == "B" // ak 21.3.04 Eval(::killer,::xbpGet) ENDIF ::xbpColumn:refreshRows( nRowPos, nRowPos ) ENDIF ::xbpGet:hide() ENDIF ::xbpColumn:hiliteRow( nRowPos, lHilite, lFrame, lRepaint ) ENDIF ELSE /* * Editiermodus ist nicht aktiv. * Reiche alle Parameter an die Superklasse weiter. */ ::xbpColumn:hiliteRow( nRowPos, lHilite, lFrame, lRepaint ) ENDIF RETURN self /* * Erzeuge das XbpGet Objekt und/oder zeige es in der aktuellen Zeile an. */ METHOD XbpGetColumn:read( nRowPos, nFirstKey ) DEFAULT nRowPos TO ::browser:rowPos IF ::activeColumn <> NIL .AND. ; ::activeColumn <> self /* * Der Browser wurde mit der Maus angeklickt w„hrend eine andere * Spalte gerade editiert wird. Beende das Editieren in dieser Spalte. */ ::activeColumn:killRead() ENDIF ::activeColumn := self IF ::xbpGet == NIL /* * Die Spalte wurde bis jetzt noch nicht editiert. Erzeuge das * XbpGet Objekt beim ersten Editieren. */ ::createXbp() ENDIF ::active := .T. ::setHome := .T. ::setPosAndSize( nRowPos ) ::xbpGet:setData() ::xbpGet:changed( .F. ) ::xbpGet:show() SetAppFocus( ::xbpGet ) IF ::xbpGet:isDerivedFrom( "XbpSLE" ) ::xbpGet:setMarked( {1,1} ) ENDIF IF nFirstKey <> NIL ::xbpGet:clear() PostAppEvent( xbeP_Keyboard, nFirstKey, NIL, ::xbpGet ) ENDIF RETURN self /* * Linke Maustaste wurde in :dataArea der Spalte gedrckt */ METHOD XbpGetColumn:_lbDown( aPos ) LOCAL nRowPos := ::dataArea:cellFromPos( aPos ) ::active := .T. IF nRowPos == ::browser:rowPos ::read( nRowPos ) ENDIF RETURN self /* * Tastaturverarbeitung * * Wenn der Edit Modus aktiv ist, wird die Methode von dem * XbpGet Objekt aufgerufen, das gerade den Eingabefokus hat. * Grund dafr ist, daá das XbpGetColumn Objekt der Controller * fr das XbpGet Objekts ist * (siehe Methode :createXbp() -> ::xbpGet:controller := self) * * - Der Editiermodus wird aktiviert durch: * 1) ENTER Taste (Zelleninhalt bleibt erhalten) * 2) Editiertaste (Zelleninhalt wird vor Editieren gel”scht) * * - Esc bricht Editieren ab. * */ METHOD XbpGetColumn:keyBoard( nKey ) LOCAL aRowPos, bBlock DO CASE CASE nKey == xbeK_ALT_F4 PostAppEvent( xbeP_Close,,, SetAppWindow() ) RETURN .T. CASE nKey == xbeK_ENTER /* * N„chste Zelle editieren oder Editiermodus einschalten */ IF ::active bBlock := {|o| o:down() } ELSE ::read( ::browser:rowPos ) ENDIF CASE .NOT. ::active /* * Tasten, die von XbpGet verarbeitet werden, schalten in den * Editiermodus um und l”schen den Zellinhalt. Andere Tasten * werden ignoriert. */ IF nKey > 31 .AND. nKey < 256 ::read( ::browser:rowPos, nKey ) ENDIF CASE nKey == xbeK_ESC /* * Žnderungen bei Esc rueckgaengig machen */ ::xbpGet:undo() ::killRead() bBlock := {|o| o:refreshCurrent() } /* * Tasten, die den Browse Curser w„hrend des Editierens bewegen * * HINWEIS: Nach der Tab Taste wird xbeK_ENTER an den Browser gesandt, * so daá das Editieren in der n„chsten oder vorherigen Spalte * fortgesetzt wird. */ CASE nkey == xbeK_TAB IF ::browser:colPos == ::browser:colCount bBlock := {|o| o:firstCol(), o:down(), ; PostAppEvent( xbeP_Keyboard, xbeK_ENTER,, o ) } ELSE bBlock := {|o| o:right(), ; PostAppEvent( xbeP_Keyboard, xbeK_ENTER,, o ) } ENDIF CASE nkey == xbeK_SH_TAB IF ::browser:colPos == 1 bBlock := {|o| o:up(), o:lastCol(), ; PostAppEvent( xbeP_Keyboard, xbeK_ENTER,, o ) } ELSE bBlock := {|o| o:left(), ; PostAppEvent( xbeP_Keyboard, xbeK_ENTER,, o ) } ENDIF CASE nkey == xbeK_DOWN bBlock := {|o| o:down() } CASE nKey == xbeK_UP bBlock := {|o| o:up() } CASE nkey == xbeK_PGDN bBlock := {|o| o:pageDown() } CASE nKey == xbeK_PGUP bBlock := {|o| o:pageUp() } CASE nkey == xbeK_CTRL_PGDN bBlock := {|o| o:goBottom() } CASE nKey == xbeK_CTRL_PGUP bBlock := {|o| o:goTop() } ENDCASE IF bBlock <> NIL /* * Browser Aktion ausl”sen */ Eval( bBlock, ::browser ) ::browser:forceStable() ENDIF /* * XbpGet braucht einen logischen Rckgabewert */ RETURN ( bBlock <> NIL ) /* * Editieren beenden */ METHOD XbpGetColumn:killRead IF ::active ::xbpGet:hide() ::active := .F. ::activeColumn := NIL SetAppFocus( ::browser ) ENDIF RETURN self METHOD XbpGetColumn:activeGet() // ak 15.01.2006 RETURN ::XbpGet