Dan
  • Dan
  • Member Topic Starter
2015-06-23T07:39:10Z
Hi,

I've noticed that the Font property doesn't populate to the header and group row cells, even though the help states that this property changes the default font for cells, headers, and combo lists.

This is easy to reproduce in VB6, simply add a iGrid to a form and add the following code to the Form_Load event:

    With iGrid1
    
        .Font.Name = "Script"
    
        .AddCol "Testing", "Testing"
    
        .AddRow bgrouprow:=True
        
        .CellValue(.RowCount, .RowTextCol) = "Testing"
        
        .AddRow
        
        .CellValue(.RowCount, 1) = "Testing"
        
    End With

The header and the first row will be displayed using MS Sans Serif, and the second row using the Script font.

The same thing happens if the font is set using the Properties window for the grid control in VB6.

Dan
Igor/10Tec
2015-06-23T14:32:19Z
Dan, as always, your comments are very helpful. Let me answer point-by-point.

Group row font

Every column has a so-called column default cell. It defines the properties of all new cells in a column, including the font. When you create a new column, the font in its default cell is copied (cloned) from the current grid font. This explains why your custom font setting works for normal cells, but not for group rows. The fact is that the text in group rows is stored in the row text column, but this column is created when iGrid is initialized, i.e. BEFORE you change the grid font in your code.

To make it work as expected, we can avoid cloning the current grid font object for all default column cells. In this case the ColDefaultCell.oFont will return Nothing by default, and all cells - both normal and group row cells - will inherit the current grid font set in iGrid.Font property.

I've reread the help file, and it seems we never documented this subtle functionality so we have a right to change it and make more expectable. However, the existing code will fail after this change as developers imply that the ColDefaultCell.oFont object is not Nothing by default and they can simply change default cell fonts without creating a new StdFont object and assigning it to this object property first.

Can I know your opinion about that?


Header font

Yes, you are right - the header font is controlled using a separate Header.Font property. iGrid.Font does not affect it anyhow.


Originally Posted by: Dan 

I've noticed that the Font property doesn't populate to the header and group row cells, even though the help states that this property changes the default font for cells, headers, and combo lists.



Do you mean only the help topic dedicated to the iGrid.Font property? Or have you seen it in other topics too?

I'm going to correct the help file, and even reflect all possible new changes related to the column default font object we are discussing, so let me know what help topics should be updated.
Dan
  • Dan
  • Member Topic Starter
2015-06-23T16:07:43Z
Hi Igor,

I've already worked around the issue myself in my code, it just took me by surprise last week and had me scratching my head for a while trying to figure out why it happened. Especially when I create a new form, set it's font to something other than MS Sans Serif, drop a new iGrid control onto the form which correctly shows the font name as set in the form, but still the header and group row cells have the MS Sans Serif font. I think it's just confusing that setting the Font property in the control properties doesn't set the font for all objects that use the font - if there were separate HeaderFont and GroupRowFont properties, for example, it would be clearer that they are set separately, but there's only one Font property that can be set. In VB6 there is no way to access the header font object in the property window.

Are you saying that the fix to this would no longer allow simply setting the Font object of a cell, and instead would have to create a StdFont object and assign it as the col default font first? That could, as you say, break a lot of code.


As a workaround that won't break code, is it possible to change the group row font only when the IDE triggers a Font Property change for the control? Or is this triggered by setting the value in code too? Or simply update the group row font when it's changed in code via the Font property of the grid, so it simply updates the StdFont object assigned already to that column?


As to the reference to the help file, it's just in the Font Property help section, where it states:

Quote:


The font defined with this property also used as iGrid header font; it also will be used as the default font for all combo lists which you'll create in the future (see the Font property for the ComboObject object).



Hope this helps :)

Regards,

Dan
Igor/10Tec
2015-06-24T11:23:22Z
Originally Posted by: Dan 

Are you saying that the fix to this would no longer allow simply setting the Font object of a cell, and instead would have to create a StdFont object and assign it as the col default font first? That could, as you say, break a lot of code.



I'm talking about the ColDefaultCell.oFont property, but not cell font (the CellFont property).

Now you can simply do this:

iGrid1.ColDefaultCell(1).oFont.Size = 16

After the fix is implemented, you will need to do this:

Set iGrid1.ColDefaultCell(1).oFont = New StdFont
iGrid1.ColDefaultCell(1).oFont.Size = 16

Or even to set the font name if you are using a non-default font:

Set iGrid1.ColDefaultCell(1).oFont = New StdFont
iGrid1.ColDefaultCell(1).oFont.Name = "Script"
iGrid1.ColDefaultCell(1).oFont.Size = 16

However, I consider this approach a proper one - as we will avoid questions like yours from which we started this discussion.

*******************

One more thing. I've re-read our help file even more carefully today, and found this (see the attached screens). The default value for the ColDefaultCell property is a CellObject object with the default values of its properties. In the help topic dedicated to CellObject we see that the default value for .oFont is Nothing, which means that the grid font should be inherited!! In fact, the current version of iGrid works not the way described in the help ;)

What can you say now regarding the fix I suggest?
Igor/10Tec attached the following image(s):
Dan
  • Dan
  • Member Topic Starter
2015-06-24T12:19:06Z
Hi Igor,

As I don't use the ColDefaultCell objects, it's a yes from me as it won't break my application :)

Dan
Igor/10Tec
2015-06-25T10:53:23Z
There is one more bad side effect of the scheme used in the current official build. If you add some cols, then change the grid's font, and then add more cols, the cols added before the grid font change will use the old font.

Here is a code snippet that demonstrates this issue:

With iGrid1

    .Font.Name = "Script"
    .AddCol "Testing", "Testing"
    
    .Font.Name = "Arial"
    .AddCol "Testing2", "Testing2"
    
    .AddRow
    
    .CellValue(.RowCount, 1) = "Testing"
    .CellValue(.RowCount, 2) = "Testing2"

End With

As you can see, the current scheme should be fixed as I suggested. I'm going to prepare a new interim build and send it to you for testing in a private email correspondence.

Anyone interested in this issue is welcome to join the discussion!
Igor/10Tec
2015-06-25T12:03:55Z
The problem from my previous post is also applicable to ComboObject.Font. When we create a combo list, the current grid's font is cloned and remembered in the ComboObject.Font property, and the drop-down part of the combo object uses this font regardless of the grid's font setting. As I can see, we need to apply the same fix to the ComboObject.Font property.

Guys, do you agree with me?
Igor/10Tec
2015-06-25T12:37:57Z
One more thought regarding the issue we are discussing. The What's New document for the grid control explains why we clone the grid's font and save it in the ColDefaultCell.Font property while creating new columns - see the change list for the v5.0.86:

Quote:

3. [Enhancement] The oFont property of the column default cell object is initialized using the copy of the current grid font when a column is created (Nothing was used in the previous versions). This allows the developer to modify the font for new cells in a column easily if a font similar to the grid font should be used, without writing many statements to clone the grid font object. For instance, now the developer can use the following statement to make the contents of all new cells italic in the newly created column:

iGrid1.AddCol.oFont.Italic = True

(the AddCol method returns a reference to the column’s default cell object).



This was a useful addition, but it causes side effects and problems we are discussing.

So do we still need the fix with creating empty ColDefaultCell.Font's by default?

My opinion - yes, because it makes the grid work properly, though you may need a couple of additional code lines.
Dan
  • Dan
  • Member Topic Starter
2015-06-26T07:41:48Z
Hi Igor,

In my own opinion I think that unless I set a font on a cell or column explicitly, it should match the Font property of the grid control itself. However, if it will only do this for new columns that's fine by me, as I'll always set the font before creating columns, either in code or using the Font property of the control in the VB6 IDE. Having the group row cell not picking up the font was the only confusing bit for me, although having the combos match would be nice too. I don't use combos much though, and where I have it's only been with the system default font so far so I'd never noticed this issue.

Dan
Oliver
2015-07-06T14:15:34Z
Hello Igor, hello Dan,

I think I was among the people who suggested the change you made in v5.0.86. For me, the reasoning was that having to create a new StdFont object every time I need to change a property of it, usuall adds two lines to a single one, making it three. As you put in your example, Igor, I need one to create the StdFont and another one to set the font name, again and again, to the same font used by the rest of the iGrid. I never use the default font of StdFont, because honestly, MS Sans Serif doesn't look too good.

So yes, it would break a lot of places in our code right now if iGrid returns to its former behaviour of having Nothing as the default for the ColDefaultCell().

I see a few solutions to this:

1. Just add a new property .oGroupRowFont as an alias for .ColDefaultCell(.RowTextCol).oFont and refer to it somewhere where the Grouping feature is explained. Dan suggested that earlier already. That would make it somewhat more obvious as to how to change the font of the group rows and hint to the fact that .oGroupRowFont doesnt change when you set .oFont in the code.

2. Lazy "Copy on read/write"
This is probably a bit more work to implement. Basically, it means that internally, you don't clone the font object for each column when they are created. You keep them empty and know that you have to use the .Font object for them instead. When the .ColDefaultCell().oFont property is read, you simply return the values of .Font, which is correct. ONLY when the .ColDefaultCell().oFont property is modified, you really create a copy of the StdFont and place it in the .ColDefaultCell.

This would give all columns the correct default behaviour, including the .ColDefaultCell(.RowTextCol), which would be to use the default of .Font unless it has been touched at some point.

As I'm writing that, I realize that you probably don't handle the properties of the .oFont objects yourself at all as it is just as StdFont anyways. So it might be difficult to catch the calls to the properties of the .oFont objects. Creating the copy whenever the .oFont objects are READ might be an alternative but that's also unexpected.



I think I'd go with solution 1. ;)

Oliver
Igor/10Tec
2015-07-07T07:56:14Z
Originally Posted by: Oliver 

I think I was among the people who suggested the change you made in v5.0.86. For me, the reasoning was that having to create a new StdFont object every time I need to change a property of it, usuall adds two lines to a single one, making it three. As you put in your example, Igor, I need one to create the StdFont and another one to set the font name, again and again, to the same font used by the rest of the iGrid. I never use the default font of StdFont, because honestly, MS Sans Serif doesn't look too good.



Let's discuss this using a typical situation. For instance, you need to use the font Tahoma for your grid, and the columns 1-3 should be bold. In the current public version 5.0.105 you do something like this:

iGrid1.Font.Name = "Tahoma"

iGrid1.ColDefaultCell(1).oFont.Bold = True
iGrid1.ColDefaultCell(2).oFont.Bold = True
iGrid1.ColDefaultCell(3).oFont.Bold = True

Yes, it's easy and clear, though this approach has other problems like I described in my post #6  above.

Ok, now we return to Nothing as the default value for ColDefaultCell.oFont. If I understand your words properly, you're going to re-code the sample above like the following one.

(sure, we can simplify it a little bit using the With statement, but it does not relate to our discussion now)

iGrid1.Font.Name = "Tahoma"

iGrid1.ColDefaultCell(1).oFont = New StdFont
iGrid1.ColDefaultCell(1).Name = "Tahoma"
iGrid1.ColDefaultCell(1).Bold = True

iGrid1.ColDefaultCell(2).oFont = New StdFont
iGrid1.ColDefaultCell(2).Name = "Tahoma"
iGrid1.ColDefaultCell(2).Bold = True

iGrid1.ColDefaultCell(3).oFont = New StdFont
iGrid1.ColDefaultCell(3).Name = "Tahoma"
iGrid1.ColDefaultCell(3).Bold = True

But buddy, I think that a much better style of programming is something like this, when all settings are gathered at one place:

iGrid1.Font.Name = "Tahoma"

Dim myFont as New StdFont
myFont.Name = iGrid1.Font.Name
myFont.Bold = True

iGrid1.ColDefaultCell(1).oFont = myFont
iGrid1.ColDefaultCell(2).oFont = myFont
iGrid1.ColDefaultCell(3).oFont = myFont


Originally Posted by: Oliver 

1. Just add a new property .oGroupRowFont as an alias for .ColDefaultCell(.RowTextCol).oFont and refer to it somewhere where the Grouping feature is explained. Dan suggested that earlier already. That would make it somewhat more obvious as to how to change the font of the group rows and hint to the fact that .oGroupRowFont doesnt change when you set .oFont in the code.



Why do we need to implement a new property that actually duplicates the existing one? Note also that .RowTextCol is a reference to the ROW TEXT column but not only to a non-existing group row column, and the row text column defines the properties of group rows and row text cells inside normal rows.


Originally Posted by: Oliver 

2. Lazy "Copy on read/write"
This is probably a bit more work to implement. Basically, it means that internally, you don't clone the font object for each column when they are created. You keep them empty and know that you have to use the .Font object for them instead. When the .ColDefaultCell().oFont property is read, you simply return the values of .Font, which is correct. ONLY when the .ColDefaultCell().oFont property is modified, you really create a copy of the StdFont and place it in the .ColDefaultCell.



Yes, it's a good idea, and in fact we are using it for our cells. When you access the CellFont property, you always get a non-empty Font object and you can change its properties directly. This virtual font object is cached inside iGrid, but this technique has some limitations. The first of them is that you cannot cache it in your code using the Set statement. Second, you have no way to know whether a cell has the default font (CellFont never returns Nothing), you can only reset the cell font to the default one using the CellDefaultFont method (argh).

We implemented this for cells to avoid storing font objects in every cell - as you understand, it would cause huge resource consuming in big grids. BTW, this is one more reason why I vote for my fix with the default column font set to Nothing. If we go this way, we also save many system resources as we do not create a new font object for every column in every grid (any system font object actually uses a lot of resources). The situation is even worse because we clone the same grid font over and over again. Frankly speaking, I'm very ashamed for this...

So guys, with all my respect to you and code you wrote, I still think that we need the fix I suggested. In the current implementation, we preferred code simplicity to proper work (as we see it now), but I believe that faultless code must be on the first place.
Oliver
2015-07-07T08:12:19Z
I agree that the additional property is not pretty. And you are right, I missed the point that the row text column is used for more that just the group rows, making the naming of the additional property difficult and misleading.

I also agree that we should not waste resources on Font objects that are never used.

So I agree we should go back to the old behaviour with the emtpy .oFont objects as default as it makes it more clear what is happening.

Oliver
2015-07-07T08:26:26Z
Since I had to work with the .oFont being Nothing before the first change, I want to share another way to deal with this:

Paraphrasing Igor's last example, I'd suggest this:


iGrid1.Font.Name = "Tahoma"

iGrid1.ColDefaultCell(1).oFont = iGrid_CloneFont(iGrid1.Font, bBold:=True)
iGrid1.ColDefaultCell(2).oFont = iGrid_CloneFont(iGrid1.Font, bBold:=True)
iGrid1.ColDefaultCell(3).oFont = iGrid_CloneFont(iGrid1.Font, bBold:=True)


Public Function iGrid_CloneFont(fntSource As StdFont, Optional bBold As Variant, Optional bUnderline As Variant, Optional iSize As Variant) As StdFont
    Dim ifnt As stdole.IFont
    Set ifnt = fntSource

    Dim fntClone As StdFont
    ifnt.Clone fntClone
    
    If (Not IsMissing(bBold)) Then
        fntClone.Bold = bBold
    End If
    If (Not IsMissing(bUnderline)) Then
        fntClone.Underline = bUnderline
    End If
    If (Not IsMissing(iSize)) Then
        fntClone.Size = iSize
    End If

    Set iGrid_CloneFont = fntClone
End Function

I don't really remember why I did the cloning via IFont.Clone instead of just copying the eight Attributes of the Font... Seems a little overly complex now that I see it.

I'm aware that this example creates three StdFont objects where only one is needed. In my application, it's only a few columns in every grid that behave differently than the default font. The example function can also easily be extended for the other Font properties, I just never had use for Italic, Charset or Strikethrough.
Igor/10Tec
2015-07-17T07:02:24Z
All the font issues we discussed above are already fixed in a new interim build of iGrid, and these fixes will be included into the next public update of iGrid.

If you need these fixes right now, let us know by sending a request to our support service.
Igor/10Tec
2015-12-01T15:17:57Z
All these problems has been solved with the release of iGrid 6.0.