From 933a678c12d78f03eec72c103a3e79cf698b4fe8 Mon Sep 17 00:00:00 2001 From: Pritpal Bedi Date: Tue, 14 Jul 2009 21:02:52 +0000 Subject: [PATCH] 2009-07-14 13:50 UTC-0800 Pritpal Bedi (pritpal@vouchcac.com) * contrib/hbxbp/xbpdialog.prg * contrib/hbxbp/xbpgeneric.prg ! Changed the way AppEvent() eventloop was being executed. Not it is more near to Xbase++, not 100% but near. CPU consumption is reduced to 2-3 percent. * contrib/hbxbp/xbprtf.prg + Implemented more XbpRTF() features. * contrib/hbxbp/tests/demoxbp.prg + Demonstrated more XbpRtf() features. Play with Rtf tab. --- harbour/ChangeLog | 14 +++ harbour/contrib/hbxbp/tests/demoxbp.prg | 143 ++++++++++++++++++------ harbour/contrib/hbxbp/xbpdialog.prg | 3 + harbour/contrib/hbxbp/xbpgeneric.prg | 109 +++++++++--------- harbour/contrib/hbxbp/xbprtf.prg | 24 ++-- 5 files changed, 195 insertions(+), 98 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index a2790643db..5ed2a0a72d 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -17,6 +17,20 @@ past entries belonging to author(s): Viktor Szakats. */ +2009-07-14 13:50 UTC-0800 Pritpal Bedi (pritpal@vouchcac.com) + * contrib/hbxbp/xbpdialog.prg + * contrib/hbxbp/xbpgeneric.prg + ! Changed the way AppEvent() eventloop was being executed. + Not it is more near to Xbase++, not 100% but near. + CPU consumption is reduced to 2-3 percent. + + * contrib/hbxbp/xbprtf.prg + + Implemented more XbpRTF() features. + + * contrib/hbxbp/tests/demoxbp.prg + + Demonstrated more XbpRtf() features. + Play with Rtf tab. + 2009-07-14 22:42 UTC+0200 Viktor Szakats (harbour.01 syenar.hu) * config/hpux/gcc.cf * config/darwin/gcc.cf diff --git a/harbour/contrib/hbxbp/tests/demoxbp.prg b/harbour/contrib/hbxbp/tests/demoxbp.prg index 4ef3223ddd..b4cf36cfa4 100644 --- a/harbour/contrib/hbxbp/tests/demoxbp.prg +++ b/harbour/contrib/hbxbp/tests/demoxbp.prg @@ -86,8 +86,8 @@ PROCEDURE Main() PROCEDURE BuildADialog() LOCAL oDlg, mp1, mp2, oXbp, nEvent, aSize, aTabs, oDa LOCAL nThread := ThreadID() - LOCAL cThread := hb_ntos( nThread ) - LOCAL aPP, oHtm + //LOCAL cThread := hb_ntos( nThread ) + LOCAL oHtm /* Create Application Window */ oDlg := GuiStdDialog( "Harbour - Xbase++ - QT Dialog [ "+ hb_ntos( nThread )+" ]" ) @@ -172,13 +172,15 @@ PROCEDURE BuildADialog() /* Enter Xbase++ Event Loop - working */ DO WHILE .t. nEvent := AppEvent( @mp1, @mp2, @oXbp ) + IF ( nEvent == xbeP_Close ) .OR. ( nEvent == xbeP_Keyboard .and. mp1 == xbeK_ESC ) -hb_outDebug( " WOW " ) +hb_outdebug( " WOW " ) EXIT ELSEIF nEvent == xbeP_Keyboard .and. mp1 == xbeK_F1 oHtm:setHTML( '

Direct HTML Injection

'+; 'This HTML content is pushed dynamically with

:setHTML()

.' ) ENDIF + oXbp:handleEvent( nEvent, mp1, mp2 ) ENDDO @@ -326,7 +328,7 @@ STATIC FUNCTION Build_MenuBar( oDlg ) oSubMenu:setColorFG( GraMakeRGBColor( { 255, 1, 1 } ) ) #ifdef __HARBOUR__ - #if 0 + #if 1 oSubMenu := XbpMenu():new( oMenuBar ):create() oSubMenu:title := "~Dialogs" #if 1 /* T H R E D E D D I A L O G */ @@ -903,7 +905,7 @@ PROCEDURE FieldStruct( oItem, aField ) /*----------------------------------------------------------------------*/ FUNCTION Build_Statics( oWnd ) - LOCAL oGrp,oLbl, oLin, oBox, oBmp, oBmp1 + LOCAL oGrp,oLbl, oLin, oBox, oBmp LOCAL nC1 := 10, nC2 := 45, nC3 := 110, nC4 := 175 LOCAL nW := 50, nH := 50, nG := 10 LOCAL nT := 60 @@ -1115,23 +1117,7 @@ FUNCTION Build_Bitmap( oWnd ) LOCAL nFrmts := { XBPBMP_FORMAT_PNG, XBPBMP_FORMAT_GIF, XBPBMP_FORMAT_JPG, ; XBPBMP_FORMAT_JPG, XBPBMP_FORMAT_WIN3X } - aFltr := {} - aadd( aFltr, { "Windows Bitmap ", "*.bmp" } ) - aadd( aFltr, { "Graphic Interchange Format ", "*.gif" } ) - aadd( aFltr, { "Joint Photographic Experts ", "*.jpg; *.jpeg" } ) - aadd( aFltr, { "Portable Network Graphics ", "*.png" } ) - aadd( aFltr, { "Portable Pixmap ", "*.ppm" } ) - aadd( aFltr, { "Tagged Image File Format ", "*.tiff" } ) - aadd( aFltr, { "X11 Bitmap ", "*.xbm" } ) - aadd( aFltr, { "X11 Pixmap ", "*.xpm" } ) - aeval( aFltr, {|e_,i| aFltr[ i,1 ] := trim( e_[ 1 ] ) } ) - - oDlg := XbpFileDialog():new( oWnd, , {10,10} ) - oDlg:title := "Select an image to be converted" - oDlg:fileFilters := aFltr - oDlg:create() - - cFile := oDlg:open( hb_DirBase(), , .f. ) + cFile := GetAnImageFile( oWnd, "Select an image to be converted" ) IF !empty( cFile ) oBmp := XbpBitmap():new():create() @@ -1166,6 +1152,30 @@ FUNCTION Build_Bitmap( oWnd ) /*----------------------------------------------------------------------*/ +FUNCTION GetAnImageFile( oWnd, cTitle ) + LOCAL aFltr := {} + + DEFAULT cTitle TO "Select an Image" + + aadd( aFltr, { "Portable Network Graphics ", "*.png" } ) + aadd( aFltr, { "Windows Bitmap ", "*.bmp" } ) + aadd( aFltr, { "Graphic Interchange Format ", "*.gif" } ) + aadd( aFltr, { "Joint Photographic Experts ", "*.jpg; *.jpeg" } ) + aadd( aFltr, { "Portable Pixmap ", "*.ppm" } ) + aadd( aFltr, { "Tagged Image File Format ", "*.tiff" } ) + aadd( aFltr, { "X11 Bitmap ", "*.xbm" } ) + aadd( aFltr, { "X11 Pixmap ", "*.xpm" } ) + aeval( aFltr, {|e_,i| aFltr[ i,1 ] := trim( e_[ 1 ] ) } ) + + oDlg := XbpFileDialog():new( oWnd, , {10,10} ) + oDlg:title := cTitle + oDlg:fileFilters := aFltr + oDlg:create() + + RETURN oDlg:open( hb_DirBase(), , .f. ) + +/*----------------------------------------------------------------------*/ + FUNCTION Build_FontDialog( oWnd ) LOCAL oDlg @@ -1222,42 +1232,63 @@ FUNCTION Build_PrintDialog( oWnd ) FUNCTION Build_Rtf( oWnd ) LOCAL oRTF, oBtn LOCAL sz_:= oWnd:currentSize() + LOCAL nW := 50, nG := 8, nH := 20, nT := sz_[2]-55 - oBtn := XbpPushButton():new( oWnd, , {10,sz_[2]-70}, {50,35} ) + oBtn := XbpPushButton():new( oWnd, , {10+(nW+nG)*0, nT}, {nW,nH} ) oBtn:caption := 'Image' oBtn:create() oBtn:activate := {|| RtfInsertImage( oRtf ) } - oBtn := XbpPushButton():new( oWnd, , {10+60,sz_[2]-70}, {50,35} ) + oBtn := XbpPushButton():new( oWnd, , {10+(nW+nG)*1, nT}, {nW,nH} ) oBtn:caption := 'Undo' oBtn:create() oBtn:activate := {|| oRtf:undo() } - oBtn := XbpPushButton():new( oWnd, , {10+120,sz_[2]-70}, {50,35} ) + oBtn := XbpPushButton():new( oWnd, , {10+(nW+nG)*2, nT}, {nW,nH} ) oBtn:caption := 'Redo' oBtn:create() #ifdef __HARBOUR__ oBtn:activate := {|| oRtf:redo() } #endif - oBtn := XbpPushButton():new( oWnd, , {10+180,sz_[2]-70}, {50,35} ) + oBtn := XbpPushButton():new( oWnd, , {10+(nW+nG)*3, nT}, {nW,nH} ) oBtn:caption := 'ULine' oBtn:create() oBtn:activate := {|| oRtf:selUnderline := .t. } - oBtn := XbpPushButton():new( oWnd, , {10+240,sz_[2]-70}, {50,35} ) + oBtn := XbpPushButton():new( oWnd, , {10+(nW+nG)*4, nT}, {nW,nH} ) oBtn:caption := 'Bold' oBtn:create() oBtn:activate := {|| oRtf:selBold := .t. } - oBtn := XbpPushButton():new( oWnd, , {10+295,sz_[2]-70}, {45,35} ) + oBtn := XbpPushButton():new( oWnd, , {10+(nW+nG)*5, nT}, {nW,nH} ) oBtn:caption := 'Italic' oBtn:create() oBtn:activate := {|| oRtf:selItalic := .t. } + oBtn := XbpPushButton():new( oWnd, , {10+(nW+nG)*0, nT-25}, {nW,nH} ) + oBtn:caption := 'Load' + oBtn:create() + oBtn:activate := {|| RtfLoadDocument( oRtf ) } + oBtn := XbpPushButton():new( oWnd, , {10+(nW+nG)*1, nT-25}, {nW,nH} ) + oBtn:caption := 'Save' + oBtn:create() + oBtn:activate := {|| RtfSaveDocument( oRtf ) } + + oBtn := XbpPushButton():new( oWnd, , {10+(nW+nG)*2, nT-25}, {nW,nH} ) + oBtn:caption := 'Font++' + oBtn:create() + oBtn:activate := {|x| x := oRTF:selFontSize, IF( x == 0, x := 11, ), oRTF:selFontSize := x+1 } + + oBtn := XbpPushButton():new( oWnd, , {10+(nW+nG)*3, nT-25}, {nW,nH} ) + oBtn:caption := 'Font--' + oBtn:create() + oBtn:activate := {|x| x := oRTF:selFontSize, IF( x == 0, x := 11, ), oRTF:selFontSize := x-1 } + + //------------------------// oRTF := XbpRtf():new( oWnd ) - oRTF:create( , , { 10,10 }, { sz_[ 1 ]-23, sz_[ 2 ]-90 } ) + oRTF:create( , , { 10,10 }, { sz_[ 1 ]-23, sz_[ 2 ]-100 } ) oRTF:setColorBG( GraMakeRGBColor( {255,255,200} ) ) oRTF:setFontCompoundName( "12.Times" ) @@ -1296,24 +1327,72 @@ FUNCTION Build_Rtf( oWnd ) oRTF:SelItalic := .T. // oRTF:SelStrikeThru := .T. /* OK */ oRTF:SelUnderline := .T. - oRTF:selAlignment := 2 //XBPRTF_SELALIGN_RIGHT + oRTF:selAlignment := XBPRTF_ALIGN_CENTER // Reset the text cursor // oRTF:SelStart := Len( oRTF:Text ) - oRTF:insertImage( 'copy.png' ) RETURN nil /*----------------------------------------------------------------------*/ STATIC FUNCTION RtfInsertImage( oRtf ) + #ifdef __HARBOUR__ + LOCAL cFile // Proivide a selection dialog - oRtf:insertImage( "abs3.png" ) + cFile := GetAnImageFile( oRtf, 'Select Image to be Inserted' ) + IF empty( cFile ) + oRtf:insertImage( "abs3.png" ) + ELSE + oRtf:insertImage( cFile ) + ENDIF + #endif + RETURN nil + +/*----------------------------------------------------------------------*/ + +STATIC FUNCTION RtfLoadDocument( oRTF ) + LOCAL oDlg, cFile, aFiltr := {} + + aadd( aFiltr, { "All Files", "*.*" } ) + aadd( aFiltr, { "Text File", "*.txt" } ) + aadd( aFiltr, { "RTF File" , "*.htm; *.html" } ) + + oDlg := XbpFileDialog():new():create( oRTF, , { 10,10 } ) + oDlg:title := "Open an RTF Document" + oDlg:center := .t. + oDlg:fileFilters := aFiltr + oDlg:setColorBG( GraMakeRGBColor( { 255,255,200 } ) ) + + cFile := oDlg:open() + IF !empty( cFile ) + oRTF:loadFile( cFile ) + ENDIF RETURN nil /*----------------------------------------------------------------------*/ +STATIC FUNCTION RtfSaveDocument( oRTF ) + LOCAL oDlg, cFile, aFiltr := {} + + aadd( aFiltr, { "RTF File" , "*.htm; *.html" } ) + aadd( aFiltr, { "Text File", "*.txt" } ) + + oDlg := XbpFileDialog():new():create( oRTF, , { 10,10 } ) + oDlg:title := "Open an RTF Document" + oDlg:center := .t. + oDlg:fileFilters := aFiltr + oDlg:setColorBG( GraMakeRGBColor( { 255,200,200 } ) ) + + cFile := oDlg:saveAs() + IF !empty( cFile ) + oRTF:saveFile( cFile ) + ENDIF + + RETURN nil + +/*----------------------------------------------------------------------*/ diff --git a/harbour/contrib/hbxbp/xbpdialog.prg b/harbour/contrib/hbxbp/xbpdialog.prg index 8bef57c2ae..2cb0b6438f 100644 --- a/harbour/contrib/hbxbp/xbpdialog.prg +++ b/harbour/contrib/hbxbp/xbpdialog.prg @@ -146,6 +146,9 @@ METHOD XbpDialog:create( oParent, oOwner, aPos, aSize, aPresParams, lVisible ) SetAppWindow( Self ) + /* Thread specific event buffer */ + InitializeEventBuffer() + /* Install Event Loop per Dialog Basis */ /* Limitng */ ::oEventLoop := QEventLoop():new( ::pWidget ) diff --git a/harbour/contrib/hbxbp/xbpgeneric.prg b/harbour/contrib/hbxbp/xbpgeneric.prg index 5f3c2c84e5..26da45c953 100644 --- a/harbour/contrib/hbxbp/xbpgeneric.prg +++ b/harbour/contrib/hbxbp/xbpgeneric.prg @@ -80,10 +80,11 @@ STATIC ts_mutex STATIC oApp -STATIC aEventLoop := {} -STATIC ts_events -//THREAD STATIC ts_events +THREAD STATIC aEventLoop := {} + +//STATIC ts_events +THREAD STATIC ts_events THREAD STATIC nEventIn := 0 THREAD STATIC nEventOut := 0 @@ -97,80 +98,82 @@ THREAD STATIC oEventLoop /*----------------------------------------------------------------------*/ INIT PROCEDURE Qt_Start() + + ts_mutex := hb_mutexCreate() + oDummy := XbpObject():new() + qt_qapplication() oApp := QApplication():new() RETURN +/*----------------------------------------------------------------------*/ + EXIT PROCEDURE Qt_End() qt_qapplication_quit() RETURN +/*----------------------------------------------------------------------*/ +/* + * Will be called from XbpDialog() | XbpCRT() + */ +FUNCTION InitializeEventBuffer() + + IF empty( ts_events ) + ts_events := array( EVENT_BUFFER ) + aeval( ts_events, {|e,i| e := e, ts_events[ i ] := { 0, NIL, NIL, NIL, -9999 } } ) + ENDIF +//xbp_debug( len( ts_events ) ) + RETURN nil + /*----------------------------------------------------------------------*/ /* * Internal to the XbpParts , Must NOT be called from Application Code */ FUNCTION SetAppEvent( nEvent, mp1, mp2, oXbp ) - //hb_mutexLock( ts_mutex ) - IF ++nEventIn > EVENT_BUFFER nEventIn := 1 ENDIF - ts_events[ nEventIn ] := { nEvent, mp1, mp2, oXbp, ThreadID() } +//xbp_debug( "SetAppEvent ... ", threadID(), nEventIn ) - //hb_mutexUnLock( ts_mutex ) + ts_events[ nEventIn,1 ] := nEvent + ts_events[ nEventIn,2 ] := mp1 + ts_events[ nEventIn,3 ] := mp2 + ts_events[ nEventIn,4 ] := oXbp + ts_events[ nEventIn,5 ] := ThreadID() RETURN nil /*----------------------------------------------------------------------*/ -FUNCTION AppEvent( mp1, mp2, oXbp ) - LOCAL nEvent, n +FUNCTION AppEvent( mp1, mp2, oXbp, nTimeout ) + LOCAL nEvent //, n - //hb_idleSleep( 0.1 ) /* May be we need QT based mechanism */ - - #if 0 - //hb_mutexLock( ts_mutex ) - oApp:processEvents() - //hb_mutexUnLock( ts_mutex ) - #else - /* Event Loop - Can be one per Application */ - - //oAppWindow:oEventLoop:processEvents() - //hb_mutexLock( ts_mutex ) - - IF( n := ascan( aEventLoop, {|e_| e_[ 2 ] == threadID() } ) ) > 0 - //hb_outDebug( "<<<<<<<<<<<< "+hb_ntos( threadID() ) ) - aEventLoop[ n,1 ]:processEvents() - //hb_outDebug( ">>>>>>>>>>>>.... "+hb_ntos( threadID() ) ) - ENDIF - - //hb_mutexUnLock( ts_mutex ) - #endif - - //hb_mutexLock( ts_mutex ) + DEFAULT nTimeout TO 0 IF ++nEventOut > EVENT_BUFFER nEventOut := 1 ENDIF +//xbp_debug( " AppEvent ... ", threadID(), nEventOut ) + DO WHILE .t. + aEventLoop[ 1,1 ]:processEvents_1( 0, 200 ) - IF empty( ts_events[ nEventOut ] ) .OR. ts_events[ nEventOut,5 ] <> ThreadID() - //nEventOut-- /* Stay back and ensure that no event is missed */ - nEvent := 0 - mp1 := NIL - mp2 := NIL - oXbp := oDummy - ELSE - //hb_outDebug( str( threadID() )+' '+ str( ts_events[ nEventOut,5 ] ) ) - nEvent := ts_events[ nEventOut,1 ] - mp1 := ts_events[ nEventOut,2 ] - mp2 := ts_events[ nEventOut,3 ] - oXbp := ts_events[ nEventOut,4 ] - ts_events[ nEventOut ] := NIL - ENDIF + IF ts_events[ nEventOut,5 ] == ThreadID() + nEvent := ts_events[ nEventOut,1 ] + mp1 := ts_events[ nEventOut,2 ] + mp2 := ts_events[ nEventOut,3 ] + oXbp := ts_events[ nEventOut,4 ] + + ts_events[ nEventOut,5 ] := -9999 /* an arbirary value never reached by ThreadID() */ + + EXIT + ENDIF + + hb_idleSleep( 0.01 ) /* Releases CPU cycles */ + ENDDO +//( "..........................", threadID() ) - //hb_mutexUnLock( ts_mutex ) RETURN nEvent /*----------------------------------------------------------------------*/ @@ -180,16 +183,6 @@ FUNCTION SetAppWindow( oXbp ) //hb_outDebug( str( threadId() )+' 0' ) - IF empty( ts_mutex ) - ts_mutex := hb_mutexCreate() - ENDIF - IF empty( ts_events ) - ts_events := array( EVENT_BUFFER ) - ENDIF - IF empty( oDummy ) - oDummy := XbpObject():new() - ENDIF - oldAppWindow := oAppWindow IF hb_isObject( oXbp ) @@ -286,11 +279,11 @@ FUNCTION SetEventFilter() FUNCTION AddEventLoop( oEventLoop ) - hb_mutexLock( ts_mutex ) + //hb_mutexLock( ts_mutex ) aadd( aEventLoop, { oEventLoop, threadID() } ) - hb_mutexUnLock( ts_mutex ) + //hb_mutexUnLock( ts_mutex ) RETURN nil diff --git a/harbour/contrib/hbxbp/xbprtf.prg b/harbour/contrib/hbxbp/xbprtf.prg index b52c283abb..118e92b7f3 100644 --- a/harbour/contrib/hbxbp/xbprtf.prg +++ b/harbour/contrib/hbxbp/xbprtf.prg @@ -208,6 +208,8 @@ METHOD XbpRtf:exeBlock( nEvent, p1 ) ::changed := .t. // .f. only at save ::change() CASE nEvent == 7 /* Xbase++ Implements */ + ::oTextCursor:configure( ::oWidget:textCursor() ) + ::oCurCursor := ::oTextCursor ::selChange() ENDCASE @@ -230,7 +232,9 @@ METHOD XbpRtf:destroy() METHOD XbpRtf:loadFile( cFile ) - HB_SYMBOL_UNUSED( cFile ) + IF file( cFile ) + ::oWidget:setText( memoread( cFile ) ) + ENDIF RETURN Self @@ -238,7 +242,11 @@ METHOD XbpRtf:loadFile( cFile ) METHOD XbpRtf:saveFile( cFile ) - HB_SYMBOL_UNUSED( cFile ) + IF ( '.txt' $ lower( cFile ) ) + memowrit( cFile, ::oWidget:toPlainText() ) + ELSE + memowrit( cFile, ::oWidget:toHTML() ) + ENDIF RETURN Self @@ -277,8 +285,8 @@ METHOD XbpRtf:find( cSearchString, nStart, nEnd, nOptions ) IF hb_isChar( cSearchString ) ::oTextDocument:pPtr := ::oWidget:document() - ::oTextCursor:pPtr := ::oTextDocument:find_2( cSearchString ) - ::oCurCursor := ::oTextCursor + ::oTextCursor:pPtr := ::oTextDocument:find_2( cSearchString ) + ::oCurCursor := ::oTextCursor ENDIF RETURN nPos @@ -483,10 +491,10 @@ METHOD XbpRtf:selFontSize( ... ) // 0 LOCAL xRet := 0 LOCAL aP := hb_aParams() - IF len( aP ) >= 1 .and. hb_isNumeric( aP[ 1 ] ) - ::oTextCharFormat:pPtr := ::oCurCursor:charFormat() - IF ::oTextCharFormat:isValid() - xRet := ::oTextCharFormat:fontPointSize() + ::oTextCharFormat:pPtr := ::oCurCursor:charFormat() + IF ::oTextCharFormat:isValid() + xRet := ::oTextCharFormat:fontPointSize() + IF len( aP ) >= 1 .and. hb_isNumeric( aP[ 1 ] ) ::oTextCharFormat:setFontPointSize( aP[ 1 ] ) ::oCurCursor:setCharFormat( QT_PTROF( ::oTextCharFormat ) ) ENDIF