Autosize ListIconGadget headings based on heading length?

Just starting out? Need help? Post your questions and find answers here.
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4749
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Autosize ListIconGadget headings based on heading length?

Post by Fangbeast »

I can already automatically resize each column in a ListIconGadget with an API but is there any way to resize the headings as well based on the heading text length?

Then I can resize the columns to fit the heading length.

Thanks
Amateur Radio, D-STAR/VK3HAF
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4663
Joined: Sun Apr 12, 2009 6:27 am

Re: Autosize ListIconGadget headings based on heading length

Post by RASHAD »

Hi Fang

Code: Select all

If OpenWindow(0, 0, 0, 640, 300, "Header Auto Resize", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ListIconGadget(0,  10,  10, 620, 200, "Column 0", 400,#PB_ListIcon_GridLines)
  SetGadgetFont(0,FontID(0))
  AddGadgetColumn(0, 1, "Column 1" , 150)
  AddGadgetColumn(0, 2, "Column 2" , 150)
  For x = 0 To 100
    AddGadgetItem(0, x, "Item "+Str(x)+Chr(10)+"Item "+Str(x)+Chr(10)+"Item "+Str(x))
  Next
  ButtonGadget(1,10,270,60,20,"Auto size")


EndIf
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Quit = 1
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 1
          SendMessage_(GadgetID(0), #LVM_SETCOLUMNWIDTH,0,#LVSCW_AUTOSIZE_USEHEADER)
          SendMessage_(GadgetID(0), #LVM_SETCOLUMNWIDTH,1,#LVSCW_AUTOSIZE_USEHEADER )
          ;SendMessage_(GadgetID(0), #LVM_SETCOLUMNWIDTH,2,#LVSCW_AUTOSIZE_USEHEADER )
      EndSelect
  EndSelect
Until Quit = 1
Egypt my love
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4749
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: Autosize ListIconGadget headings based on heading length

Post by Fangbeast »

AHA!!!! I knew there was an API for that!!! Since the data is smaller in length, I wanted the header to be fully visible anyway.

Thanks for that. I can play tomorrow Master RASHAD.

Just imported 28,000 weather station events into my little program and adding listing, viewing and eventually (I hope), graphs. (Was looking at your bar graphs for that, interesting stuff to be sure)
Amateur Radio, D-STAR/VK3HAF
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4749
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: Autosize ListIconGadget headings based on heading length

Post by Fangbeast »

Okay, it's not working the way I thought. It's resizing the columns of data to the size of the biggest item of data but that's not what I wanted.

These are some of my column headings and data the way I want them to look: (All columns of data expanded to the length of their column headings)

Code: Select all

DateTime     Dewpoint  HeatIndex   IndoorHumidity  IndoorTemperature OutdoorHumidity
12/02/2017  12.3         62              14                     22c                       129
This is the way it is now. Neither the columns nor the headings are resized. I want the columns to be resized based on the length of the header in which it belongs.

Code: Select all

DateTi..        DewPo..    Heatin...     IndoorHum.....   IndoorTem........     OutdoorHumi....
23/12/2...    57            76              48                     74.4                      57
Sorry RASHAD, I probably am not explaining it very well. And I could not tab align the data in this forum post.
Amateur Radio, D-STAR/VK3HAF
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Autosize ListIconGadget headings based on heading length

Post by IdeasVacuum »

Hi Fang,

Since your header text width is always greater than the value width, you can use a little Procedure to get the widths and then apply them:

Code: Select all

Procedure.i GetHeaderColWidth(sColHeaderTxt.s, iFontID.i)
;#-------------------------------------------------------
;This Procedure does not draw anything, it just verifies text width in pixels
Protected iHeaderColW.i

              If StartDrawing(WindowOutput(#WinMain))

                      DrawingMode(#PB_2DDrawing_Default)
                      DrawingFont(iFontID)
                      iHeaderColW = TextWidth(sColHeaderTxt)
                      StopDrawing()
              EndIf

              ProcedureReturn(iHeaderColW)
EndProcedure
Then you can set the column width and justification:

Code: Select all

Procedure JustifyListCol(iListIconID.i, iCol.i, iFlag.i, iColWidth.i)
;#-------------------------------------------------------------------
;Justify ListIcon and Set Column Width
;Column Flag: 1 = Left, 2 = Right, 3 = Center

Protected lvc.LV_COLUMN

          lvc\Mask = #LVCF_FMT

              Select iFlag

                            Case 1: lvc\fmt = #LVCFMT_LEFT
                            Case 2: lvc\fmt = #LVCFMT_RIGHT
                            Case 3: lvc\fmt = #LVCFMT_CENTER
                           Default: lvc\fmt = #LVCFMT_LEFT
              EndSelect

              SendMessage_(GadgetID(iListIconID), #LVM_SETCOLUMNWIDTH, iCol, iColWidth)
              SendMessage_(GadgetID(iListIconID), #LVM_SETCOLUMN, iCol, @lvc)
EndProcedure
Those two Procedures could of course be combined into one.

If there is a chance that a column value width is wider than the header width, you can:
1) Hide the ListIcon;
2) Find the widest Value for each column, measured in chars, with Len(sVal) and compare to respective Header text width;
3) Size the column to either Header or Value, whichever is widest, via the Procedures above;
4) Populate the ListIcon;
5) Unhide the ListIcon.

If you set the redraw attribute for the ListIcon, you probably won't need to hide it as the whole process should be fast enough anyway:

Code: Select all

SendMessage_(GadgetID(iListID),#WM_SETREDRAW,0,0) ;Faster update
;Define Col widths and populate the ListIcon
SendMessage_(GadgetID(iListID),#WM_SETREDRAW,1,0)
I often define ListIcon columns this way because the sizes can be re-used for PDF table output.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4663
Joined: Sun Apr 12, 2009 6:27 am

Re: Autosize ListIconGadget headings based on heading length

Post by RASHAD »

Hi Fang
Let MS do it for you :)

Code: Select all

Procedure AUTOSIZE_USEHEADER(gadget,font)
  text$ = GetGadgetItemText(gadget,-1,0)
  li = ListIconGadget(#PB_Any,0,0,0,0,text$,0)
  SetGadgetFont(li,FontID(font))
  Header = SendMessage_(GadgetID(gadget), #LVM_GETHEADER, 0, 0)
  nColumns = SendMessage_(Header,  #HDM_GETITEMCOUNT, 0, 0)
  
  For column = 1 To nColumns
    text$ = GetGadgetItemText(gadget,-1,column)
    AddGadgetColumn(li,column, text$ , 0)
  Next
  
  For column = 0 To nColumns
    SendMessage_(GadgetID(li), #LVM_SETCOLUMNWIDTH,column,#LVSCW_AUTOSIZE_USEHEADER)
  Next
  
  For column = 0 To nColumns
    Value = GetGadgetItemAttribute(li, 0, #PB_ListIcon_ColumnWidth ,column)
    SetGadgetItemAttribute(gadget, 0, #PB_ListIcon_ColumnWidth , Value,column)
  Next
  
  FreeGadget(li)   
EndProcedure

LoadFont(0,"tahoma",12)

If OpenWindow(0, 0, 0, 640, 300, "Header Auto Resize", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ListIconGadget(0,  10,  10, 620, 200, "Column 0", 400,#PB_ListIcon_GridLines)
  SetGadgetFont(0,FontID(0))
  AddGadgetColumn(0, 1, "Column 1" , 150)
  AddGadgetColumn(0, 2, "Column 2" , 150)
  For x = 0 To 100
    AddGadgetItem(0, x, "Item Item item item item item "+Str(x)+Chr(10)+"Item "+Str(x)+Chr(10)+"Item Item item item item item "+Str(x))
  Next
  ButtonGadget(1,10,270,60,20,"Auto size")

EndIf
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Quit = 1
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 1
          AUTOSIZE_USEHEADER(0,0)
      EndSelect
  EndSelect
Until Quit = 1
Egypt my love
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4749
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: Autosize ListIconGadget headings based on heading length

Post by Fangbeast »

Thank you very much you two geniuses (or should that be "Genii??")

Another problem solved, just several thousand to go:):)

So many programs to rewrite to bring them up to spec..so damned tired.
Amateur Radio, D-STAR/VK3HAF
User avatar
skywalk
Addict
Addict
Posts: 3996
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: Autosize ListIconGadget headings based on heading length

Post by skywalk »

Thanks for the api RASHAD,
I prefer to use the max of column data and header text.

Code: Select all

; Go back and get max text widths for each column.
; I'm only using 1 row's value but it could be extended to all.
For index = 0 To columns - 1
  SendMessage_(GadgetID(gadget), #LVM_SETCOLUMNWIDTH, index, #LVSCW_AUTOSIZE_USEHEADER)
  hdrWd = GetGadgetItemAttribute(Gadget, 0, #PB_ListIcon_ColumnWidth, index)
  SendMessage_(GadgetID(gadget), #LVM_SETCOLUMNWIDTH, index, #LVSCW_AUTOSIZE)
  dataWd = GetGadgetItemAttribute(Gadget, 0, #PB_ListIcon_ColumnWidth, index)
  SetGadgetItemAttribute(Gadget, 0, #PB_ListIcon_ColumnWidth, max(hdrWd, dataWd), index)
Next index
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4663
Joined: Sun Apr 12, 2009 6:27 am

Re: Autosize ListIconGadget headings based on heading length

Post by RASHAD »

Hi skywalk
Using Header or Columns without any fake ListIcon()

Code: Select all

Procedure AUTOSIZE_USEHEADER(gad,font)
  Header = SendMessage_(GadgetID(gad), #LVM_GETHEADER, 0, 0)
  nColumns = SendMessage_(Header,  #HDM_GETITEMCOUNT, 0, 0)
  For col = 0 To ncolumns - 1
      text$ = GetGadgetItemText(gad, -1,col)
      StartDrawing(WindowOutput(0))
        DrawingFont(FontID(font))
        width = TextWidth(Text$)+12
      StopDrawing()
      SetGadgetItemAttribute(gad, -1, #PB_ListIcon_ColumnWidth, width,col)
  Next   
EndProcedure

Procedure AUTOSIZE_USECOLUMN(gad,font)
  Header = SendMessage_(GadgetID(gad), #LVM_GETHEADER, 0, 0)
  nColumns = SendMessage_(Header,  #HDM_GETITEMCOUNT, 0, 0)
  For col = 0 To ncolumns - 1
    width = 0:oldwidth = 0
    For item = 0 To CountGadgetItems(gad)    
      text$ = GetGadgetItemText(gad,item , col)
      StartDrawing(WindowOutput(0))
        DrawingFont(FontID(font))
        width = TextWidth(Text$)+12
      StopDrawing()
      If width > oldwidth
        SetGadgetItemAttribute(gad, -1, #PB_ListIcon_ColumnWidth, width,col)
      EndIf
      oldwidth = width
    Next
  Next   
EndProcedure

LoadFont(0,"Tahoma",14)

If OpenWindow(0, 0, 0, 640, 300, "Header Auto Resize", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ListIconGadget(0,  10,  10, 620, 200, "Column 0", 400,#PB_ListIcon_GridLines)
  
  AddGadgetColumn(0, 1, "Column 1" , 150)
  AddGadgetColumn(0, 2, "Column 2" , 150)
  For x = 0 To 100
    AddGadgetItem(0, x, "Item Item item item item item "+Str(x)+Chr(10)+"Item "+Str(x)+Chr(10)+"Item Item item item item item "+Str(x))
  Next
  SetGadgetFont(0,FontID(0))
  ButtonGadget(1,10,270,70,20,"Use Header")
  ButtonGadget(2,100,270,70,20,"Use Column")

EndIf
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Quit = 1
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 1
          AUTOSIZE_USEHEADER(0,0)
          
        Case 2
          AUTOSIZE_USECOLUMN(0,0)
          
      EndSelect
  EndSelect
Until Quit = 1

Egypt my love
User avatar
Michael Vogel
Addict
Addict
Posts: 2677
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Autosize ListIconGadget headings based on heading length?

Post by Michael Vogel »

Hm, time for continuing this thread?

Was wondering if AutoSize_UseColumn could be speeded up a little bit (see line with '***'), everything else is original Rashad code. :wink:

Code: Select all

Procedure AUTOSIZE_USEHEADER(gad,font)
	Header = SendMessage_(GadgetID(gad), #LVM_GETHEADER, 0, 0)
	nColumns = SendMessage_(Header,  #HDM_GETITEMCOUNT, 0, 0)
	For col = 0 To ncolumns - 1
		text$ = GetGadgetItemText(gad, -1,col)
		StartDrawing(WindowOutput(0))
		DrawingFont(FontID(font))
		width = TextWidth(Text$)+12
		StopDrawing()
		SetGadgetItemAttribute(gad, -1, #PB_ListIcon_ColumnWidth, width,col)
	Next
EndProcedure
Procedure AUTOSIZE_USECOLUMN(gad,font)
	Header = SendMessage_(GadgetID(gad), #LVM_GETHEADER, 0, 0)
	nColumns = SendMessage_(Header,  #HDM_GETITEMCOUNT, 0, 0)
	For col = 0 To ncolumns - 1
		width = 0:oldwidth = 0
		newwidth=0
		For item = 0 To CountGadgetItems(gad)
			text$ = GetGadgetItemText(gad,item , col)
			StartDrawing(WindowOutput(0))
			DrawingFont(FontID(font))
			width = TextWidth(Text$)+12;	*** would change that to 8 ***
			StopDrawing()
			If width > newwidth; 		***
				newwidth=width;		***
			EndIf;					***
		Next
		SetGadgetItemAttribute(gad, -1, #PB_ListIcon_ColumnWidth, newwidth,col);	***
	Next
EndProcedure

LoadFont(0,"Segoe UI SemiLight",12)

If OpenWindow(0, 0, 0, 570, 305, "Header Auto Resize", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	ListIconGadget(0,10,10,550,250, "Column 0", 400,#PB_ListIcon_GridLines)

	AddGadgetColumn(0, 1, "Column 1" , 150)
	AddGadgetColumn(0, 2, "Column 2" , 150)
	For x = 0 To 100
		AddGadgetItem(0, x, "Item Item item item item item "+Str(x)+Chr(10)+"Item "+Str(x)+Chr(10)+"Item Item item item item item "+Str(x))
	Next
	SetGadgetFont(0,FontID(0))
	ButtonGadget(1,10,270,150,28,"Header length")
	ButtonGadget(2,210,270,150,28,"Column content (slow)")
	ButtonGadget(3,410,270,150,28,"Complete width")

EndIf
Repeat
	Select WaitWindowEvent()
	Case #PB_Event_CloseWindow
		Quit = 1
	Case #PB_Event_Gadget
		Select EventGadget()
		Case 1
			AUTOSIZE_USEHEADER(0,0)

		Case 2
			AUTOSIZE_USECOLUMN(0,0)

		Case 3
			SendMessage_(GadgetID(0), #LVM_SETCOLUMNWIDTH,0,#LVSCW_AUTOSIZE_USEHEADER)
			SendMessage_(GadgetID(0), #LVM_SETCOLUMNWIDTH,1,#LVSCW_AUTOSIZE_USEHEADER )
			SendMessage_(GadgetID(0), #LVM_SETCOLUMNWIDTH,2,#LVSCW_AUTOSIZE_USEHEADER )

		EndSelect
	EndSelect
Until Quit = 1
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4663
Joined: Sun Apr 12, 2009 6:27 am

Re: Autosize ListIconGadget headings based on heading length?

Post by RASHAD »

Hi MV

Code: Select all

Procedure AUTOSIZE_USEHEADER(gad,font)
  Header = SendMessage_(GadgetID(gad), #LVM_GETHEADER, 0, 0)
  nColumns = SendMessage_(Header,  #HDM_GETITEMCOUNT, 0, 0)
  For col = 0 To ncolumns - 1
    text$ = GetGadgetItemText(gad, -1,col)
    StartDrawing(WindowOutput(0))
    DrawingFont(FontID(font))
    width = TextWidth(Text$)+12
    StopDrawing()
    SetGadgetItemAttribute(gad, -1, #PB_ListIcon_ColumnWidth, width,col)
  Next
EndProcedure

Procedure AUTOSIZE_USECOLUMN(gad,font)
  Header = SendMessage_(GadgetID(gad), #LVM_GETHEADER, 0, 0)
  nColumns = SendMessage_(Header,  #HDM_GETITEMCOUNT, 0, 0)
  For col = 0 To ncolumns - 1
    width = 0:oldwidth = 0
    newwidth=0
    For item = 0 To CountGadgetItems(gad)
      text$ = GetGadgetItemText(gad,item , col)
      StartDrawing(WindowOutput(0))
      DrawingFont(FontID(font))
      width = TextWidth(Text$)+12;	*** would change that to 8 ***
      StopDrawing()
      If width > newwidth; 		***
        newwidth=width   ;		***
      EndIf              ;					***
    Next
    SetGadgetItemAttribute(gad, -1, #PB_ListIcon_ColumnWidth, newwidth,col);	***
  Next
EndProcedure

Procedure Full_AUTOSIZE(gad,font,fontname$,fontsize)
  LoadFont(font,fontname$,fontsize)
  SetGadgetFont(gad,FontID(font))
  Header = SendMessage_(GadgetID(gad), #LVM_GETHEADER, 0, 0)
  nColumns = SendMessage_(Header,  #HDM_GETITEMCOUNT, 0, 0)
  For col = 0 To ncolumns - 1
    SendMessage_(GadgetID(gad), #LVM_SETCOLUMNWIDTH, col,#LVSCW_AUTOSIZE_USEHEADER & #LVSCW_AUTOSIZE)
  Next
EndProcedure

LoadFont(0,"Segoe UI SemiLight",12)

If OpenWindow(0, 0, 0, 570, 305, "Header Auto Resize", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ListIconGadget(0,10,10,550,250, "Column 0", 150,#PB_ListIcon_GridLines)
  
  AddGadgetColumn(0, 1, "Column 1" , 150)
  AddGadgetColumn(0, 2, "Column 2" , 150)
  For x = 0 To 100
    AddGadgetItem(0, x, "Item Item item item item item "+Str(x)+Chr(10)+"Item "+Str(x)+Chr(10)+"Item Item item item item item "+Str(x))
  Next
  SetGadgetFont(0,FontID(0))
  ButtonGadget(1,10,270,150,28,"Header length")
  ButtonGadget(2,210,270,150,28,"Column content (slow)")
  ButtonGadget(3,410,270,150,28,"Complete width")
  
EndIf
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Quit = 1
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 1
          AUTOSIZE_USEHEADER(0,0)
          
        Case 2
          AUTOSIZE_USECOLUMN(0,0)
          
        Case 3
          Full_AUTOSIZE(0,1,"Georgia",14)
          
      EndSelect
  EndSelect
Until Quit = 1
Egypt my love
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4749
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: Autosize ListIconGadget headings based on heading length?

Post by Fangbeast »

7 years later and this is still very useful. Hello master RASHAD!!! Still hanging in there???
Amateur Radio, D-STAR/VK3HAF
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4663
Joined: Sun Apr 12, 2009 6:27 am

Re: Autosize ListIconGadget headings based on heading length?

Post by RASHAD »

Hi Fang
Very very very glad to here from you :)
Keep in touch from time to time it makes me happy to read from you
Egypt my love
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4749
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: Autosize ListIconGadget headings based on heading length?

Post by Fangbeast »

RASHAD I tried to a few times but you have PM off and I didn't want to reply in the forum and fill it with my waffle:):)
Amateur Radio, D-STAR/VK3HAF
Post Reply