Page 1 of 1

DCBROWSE with showing / hiding columns

Posted: Wed Jan 08, 2014 4:05 am
by reganc
Hi all

We have a screen that we import a set of product data into from various suppliers. After reading the data, we show the array of imported data using a simple DCBROWSE.

As each supplier will supply a different set of data, there could be between 2 and 50 fields of data read.

The DCBROWSE to show the imported data is built into the main import dialog, so all 50 columns are added to the getlist when the dialog is built.

I would like to only show the fields relevant to the actual data imported, so I was thinking of hiding the columns have not had data imported into.
I have an array of logical values for each column which holds a TRUE if a column has had data imported into it and I added a HIDE clause on each column that references the contents of that array.

This works but the column hiding done when the display is refreshed is visible. And by visible, I mean you can see it shifting the columns around. If this process were relatively fast, I may not have any issue with it. But unfortunately it is painfully slow.

So my question is:

Is there a way to have the column showing / hiding process happen without it being visible?

Alternatively, is there a way of creating the DCBROWSE on the fly after the data is read? I know there has been a thing mentioned about adding objects to a getlist after a dialog has been built but I have no knowledge of that or any disadvantages / pitfalls related to it.

Can anyone help?

Re: DCBROWSE with showing / hiding columns

Posted: Wed Jan 08, 2014 5:26 am
by Tom
I suggest to use AddColumn/DelColumn instead of the HIDE clause. It never worked correctly, and even it does, you may get problems with visual styles (headers) and other things.

So create the browse in a hidden dialog, delete the not used columns and show the dialog afterwards.

DCQUICKBROWSE may be an alternative.

Re: DCBROWSE with showing / hiding columns

Posted: Wed Jan 08, 2014 8:59 am
by rdonnay
I agree with Tom.
Hiding and showing columns is a bit complicated and doesn't always work good.

Re: DCBROWSE with showing / hiding columns

Posted: Wed Jan 08, 2014 9:11 am
by reganc
Thanks for the ideas, Tom.

Never used DCQUICKBROWSE. I can see that the clauses use arrays to build it so maybe it might be an easy option if what I have done cannot be refined/adjusted.

As for AddColumn/DelColumn, I wouldn't know where to start. My problem there is mixing it with the existing DC_xxx objects in the getlist.

I was thinking it would be easier for me to use DCREAD ... EXIT / SAVE with the dc_mergegetlist function to add objects but then I may have problems removing those merged getlist items / objects and adding new ones after.

Re: DCBROWSE with showing / hiding columns

Posted: Wed Jan 08, 2014 9:32 am
by reganc
rdonnay wrote:I agree with Tom.
Hiding and showing columns is a bit complicated and doesn't always work good.
Roger

Can you point me to the piece of code that handles the DCBROWSECOL ... HIDE functionality?

As far as I can see the native oColumn:hide() and oColumn:show() methods work fine except all they do is show / hide the column within the browse staticarea leaving the space/area in which they were shown as empty space between the visible columns.

And to fix this code would need to be added to walk through the static area childlist and reposition the visible columns, resize the staticarea and move the scrollbars as appropriate.

Or is there more to it than that?

Re: DCBROWSE with showing / hiding columns

Posted: Thu Jan 09, 2014 4:23 am
by reganc
I finally got something acceptable working.

I still use the HIDE clause on the DCBROWSECOL lines. The DCBROWSE itself has no HIDE clause. But it is the child of a DCSTATIC object which does have a HIDE clause.

I therefore hide() the browse object before the dc_getrefresh() and then show() it afterwards. I also added another static object with the caption 'please wait...' and show/hide this at the same time.

It may not be perfect but is visually less 'jarring' than having it visible while its doing its stuff.

I was really looking for a oBrowse:lockupdate() type fix as I thought that would be easy but this will have to do.

Re: DCBROWSE with showing / hiding columns

Posted: Thu Jan 09, 2014 5:17 am
by Cliff Wiernik
This is how we move columns. We have a static set of columns, same total, but display in different orders depending on the order.

Code: Select all

        CASE nColumnFormat == 2
          oBrowSearch:MoveColumn(1,6)                                           //  standard format #2, move column 6 right one column
          oBrowSearch:MoveColumn(-3,9)                                          //                      move column 9 left three columns
          nColumnFormat := 3

Re: DCBROWSE with showing / hiding columns

Posted: Fri Jan 10, 2014 2:15 am
by reganc
Cliff Wiernik wrote:This is how we move columns. We have a static set of columns, same total, but display in different orders depending on the order.

Code: Select all

        CASE nColumnFormat == 2
          oBrowSearch:MoveColumn(1,6)                                           //  standard format #2, move column 6 right one column
          oBrowSearch:MoveColumn(-3,9)                                          //                      move column 9 left three columns
          nColumnFormat := 3
I will keep this in mind. I suppose I could have just used this to shift the used columns to the left and left the others on the right side.

If the method I have used causes any problems I will try that instead.

Thanks.

Re: DCBROWSE with showing / hiding columns

Posted: Fri Jan 10, 2014 9:10 am
by rdonnay
Can you point me to the piece of code that handles the DCBROWSECOL ... HIDE functionality?
This is accomplished via the WhenHideEval() method of DC_XbpColumn() in _DCXBROW.PRG.

Code: Select all

* --------- This is from build 227. It works for John Lau,
* --------- The commented out version was from 232.
* --------- It didn't work for him.  I don't know why.
* --------- I'd like to find a version that works for everyone
* --------- For now, wer'e going with this until somebody complains

METHOD DC_XbpColumn:WhenHideEval( lEnable, lShow, lProtect )

LOCAL oParent, nColumn, j, oColumn, nInsColumn, lOk

Grok(lShow)

IF Valtype(::hideBlock) = 'B'
  oParent := ::parent
  nColumn := ::columnPos
  IF Eval(::hideBlock,self)
    lOk := .f.
    FOR j := 1 TO oParent:colCount
      oColumn := oParent:getColumn(j)
      IF oColumn:columnPos == nColumn // column has not been deleted
        lOk := .t.
        EXIT
      ENDIF
    NEXT
    IF lOk
      oParent:lockUpdate(.t.)
      IF !Empty(oParent:freezeLeft)
        oParent:setLeftFrozen({})
      ENDIF
      oParent:delColumn(j)
    ENDIF
  ELSE
    lOk := .t.
    nInsColumn := 1
    FOR j := 1 TO oParent:colCount
      oColumn := oParent:getColumn(j)
      IF oColumn:columnPos == nColumn   // column is already in browse
        lOk := .f.
        EXIT
      ELSEIF oColumn:columnPos < nColumn
        nInsColumn := j
      ENDIF
    NEXT
    IF lOk
      IF nColumn > 1
        nInsColumn++
      ENDIF
      IF oParent:colCount == 0
        nInsColumn := 1
      ENDIF
      oParent:lockUpdate(.t.)
      IF !Empty(oParent:freezeLeft)
        oParent:setLeftFrozen({})
      ENDIF
      oParent:insColumn(nInsColumn, self)
    ENDIF
  ENDIF
  IF lOk
    IF !Empty(oParent:freezeLeft)
      oParent:setLeftFrozen(oParent:freezeLeft)
    ENDIF
    oParent:lockUpdate(.f.)
    oParent:forceStable()
    oParent:refreshAll()
    oParent:invalidateRect()
  ENDIF
ENDIF

IF Valtype(::whenBlock) = 'B'
  lEnable := Eval(::whenBlock,self)
  IF lEnable
    ::enable()
  ELSE
    ::disable()
  ENDIF
ENDIF

IF Valtype(lProtect) == 'L' .AND. Valtype(::protectBlock) == 'B'
  lProtect := Eval(::protectBlock,self)
ENDIF

RETURN self

Re: DCBROWSE with showing / hiding columns

Posted: Wed Jan 15, 2014 5:02 am
by reganc
rdonnay wrote:
Can you point me to the piece of code that handles the DCBROWSECOL ... HIDE functionality?
This is accomplished via the WhenHideEval() method of DC_XbpColumn() in _DCXBROW.PRG.

....
oParent:lockUpdate(.f.)
oParent:forceStable()
oParent:refreshAll()
oParent:invalidateRect()
....
Shouldn't the lockupdate(.f.) line be immediately before the invalidaterect() line?