Jump to content


Photo

[Lib] Progress - Create graphical progress bars


  • Please log in to reply
9 replies to this topic

#1 Banane

Banane
  • Members
  • 46 posts

Posted 18 January 2011 - 04:52 PM

Progress - Graphical Progressbars

Description:
This library contains functions to create, and change existing, graphical progressbars.
The created progressbars are are independent of the Standard Progress Controls but rely on images.

Programmed using / for AHK, but should work with AHK_L as well.

Functions:
Progress_Add
Progress_Set
Progress_Get
Progress_Show
Progress_Hide
Progress_SetFile
Progress_SetText
Progress_SetVisibility

Progress_IsID
Progress_CopyFiles

Library:
;------------------------------------------------------------------------------------------------------------------------------------
;Function:     Progress_Add
;Parameters:   Gui      = Gui Number
;              Position = The progressbar's position within the gui, x y w h, like the standard controls
;              Range    = The value's range, default is 0 to 100
;              Value    = The progressbar's start value, default is 0
;              Text     = The text to show on top of the progressbar, may contain any of the following "variables:"
;                         $Percent  - Replaced with the progressbar's percent value
;                         $Range    - Replaced with the progressbar's range (the highest possible value)
;                         $Position - Replaced with the progressbar's current position
;                         Text is only valid and added if Vertical=0
;              Vertical = If this value is 1 a vertical progressbar will be created
;Return Value: Handle for all other functions
;------------------------------------------------------------------------------------------------------------------------------------
Progress_Add(Gui,Position,Range="0-100",Value=0,Text="",Vertical=0) {
 global
 static Progress_Count
 local File1,File2,PosX,PosY,PosW,PosH,Handle

  ;Parse through the positions
  Loop, Parse, Position, % A_Space, % A_Space
    N := SubStr(A_LoopField,1,1),Pos%N% := SubStr(A_LoopField,2,StrLen(A_LoopField))
  ;Retrieve the last set graphics
  File1 := Progress_SetFile("@Get"),File2 := Progress_SetFile("","@Get")

  ;If the graphics don't exist, or the position is incomplete, indicate the error
  If (!PosX || !PosY || !PosW || !PosH || !InStr(Range,"-") || !FileExist(File1) || !FileExist(File2))
    Return 0
  ;Increase the count of added progressbars
  Progress_Count ++
  ;Create the bar graphics and add them onto the gui
  If (Vertical = 0) {
    ;Create the handle to this progressbar
    Handle := Gui "|" Value "|" Range "|" PosW "|" Progress_Count "|" Vertical "|" Text "|" File1 "|" File2
    Gui, % Gui ":Add", Picture, % "x" PosX " y" PosY " w" PosW " h" PosH " +BackgroundTrans vPBar_" Gui "_" Progress_Count "N", % File1
    Gui, % Gui ":Add", Picture, % "x" PosX " y" PosY " w1 h" PosH " +BackgroundTrans vPBar_" Gui "_" Progress_Count "R", % File2
    If (Text != "")
      Gui, %Gui%:Add, Text, x%PosX% y%PosY% w%PosW% h%PosH% +BackgroundTrans +Center +0x200 vPBar_%Gui%_%Progress_Count%T
  } Else {
    ;Create the handle to this progressbar
    Handle := Gui "|" Value "|" Range "|" PosH "|" Progress_Count "|" Vertical "||" File1 "|" File2
    Gui, % Gui ":Add", Picture, % "x" PosX " y" PosY " w" PosW "h "PosH " +BackgroundTrans vPBar_" Gui "_" Progress_Count "N", % File1
    Gui, % Gui ":Add", Picture, % "x" PosX " y" PosY " w" PosW "h1 +BackgroundTrans vPBar_" Gui "_" Progress_Count "R", % File2
  }
  ;Apply the starting value
  Progress_Set(Handle,Value),Progress_SetText(Handle)
  ;Return all values as a handle
  Return Handle
}

;------------------------------------------------------------------------------------------------------------------------------------
;Function:     Progress_Get
;Parameters:   ID   = The handle returned by Progress_Add
;              Type = "Position" or "1" to retrieve the current value / position
;                     "Percent" or "2" to retrieve the percent of the current value / position
;                     "Range" or "3" to retrieve the range (highest possible value)
;                     "Visibility" or "4" to retrieve the progressbars visibility (Boolean)
;                     "Text" or "5" to retrieve the progressbars current text, if there's any
;Return Value: Depends on the used Type
;------------------------------------------------------------------------------------------------------------------------------------
Progress_Get(ByRef ID,Type=1) {
  ;Retrieve every value from the handle
  Loop, Parse, ID, |
    PB%A_Index% := A_LoopField
  ;Only retrieve the endvalue of the range
  PB3 := SubStr(PB3,InStr(PB3,"-") + 1,StrLen(PB3))
  ;Return the position or percent, based on the passed type
  If (Type = "Position" || Type = 1)
    Out := PB2
  Else If (Type = "Percent" || Type = 2)
    Out := Round(PB2 / PB3 * 100)
  Else If (Type = "Range" || Type = 3)
    Out := PB3
  Else If (Type = "Visibility" || Type = 4)
    GuiControlGet, Out, Visible, PBar_%PB1%_%PB5%R
  Else If (Type = "Text" || Type = 5)
    Out := PB7
  Else If (Type = "BackgroundImage" || Type = 6)
    Out := PB8
  Else If (Type = "ProgressImage" || Type = 7)
    Out := PB9
  Return Out
}

;------------------------------------------------------------------------------------------------------------------------------------
;Function:     Progress_Set
;Parameters:   ID    = The handle returned by Progress_Add
;              Value = The new value / position of the progressbar, if Range=0, you may use + - operators (+10, -5,...,...)
;              Range = If this value is equal to one, not the value / position will be set, but the range (highest possible value)
;Return Value: 0 - Invalid handle
;------------------------------------------------------------------------------------------------------------------------------------
Progress_Set(ByRef ID,Value,Range=0) {
  ;Retrieve every value from the handle
  Loop, Parse, ID, |
    PB%A_Index% := A_LoopField
  ;Break if any of the neccessary values isn't set
  If ((Range = 0 && Value = PB2) || (Range != 0 && Value = PB3) || (PB1 = "" || PB3 = "" || PB4 = "" || PB5 = ""))
    Return 0
  ;If Range is set to one, then set the value range to the passed value
  If (Range = 1)
    PB3 := Value,Value := PB2
  ;If Range is set to zero, then also recognize the + - operators
  Else
    ;Check if value was passed with an operator
    If (SubStr(Value,1,1) = "+")
      Value := PB2 + SubStr(Value,2,StrLen(Value))
    Else If (SubStr(Value,1,1) = "-")
      Value := PB2 - SubStr(Value,2,StrLen(Value))
  ;Split the start and end range value
  Start := SubStr(PB3,1,InStr(PB3,"-") - 1)
  End   := SubStr(PB3,InStr(PB3,"-") + 1,StrLen(PB3))
  ;If the value is higher than the range, use the range, and if it's lower than 0, use 0
  Value := (Value > End) ? End : (Value < Start) ? Start : Value
  ;Calculate the current percent
  Percent  := Value / End * 100
  ;Calculate and apply the new size
  If (PB6 = 0)
    GuiControl, % PB1 ":Move", % "PBar_" PB1 "_" PB5 "R", % "w" PB4 * Percent / 100
  Else GuiControl, % PB1 ":Move", % "PBar_" PB1 "_" PB5 "R", % "h" PB4 * Percent / 100
  ;Update the handles content
  ID := PB1 "|" Value "|" PB3 "|" PB4 "|" PB5 "|" PB6 "|" PB7 "|" PB8 "|" PB9
  Progress_SetText(ID)
  ;If new range was set, apply the value again
  If (Range = 1)
    Progress_Set(Handle,Value)
  Return 1
}

;------------------------------------------------------------------------------------------------------------------------------------
;Function:     Progress_SetFile
;Parameters:   Background = Path to the new background picture, or @Get to retrieve the current path
;              Progress   = Path to the new progress picture, or @Get to retrieve the current path
;              ID         = If this parameter is empty, the specified images only count for progressbars that are added afterwards
;                           Otherwise, the images of the specified progressbar will be changed
;Return Value: Depends on the parameters
;------------------------------------------------------------------------------------------------------------------------------------
Progress_SetFile(Background="",Progress="",ByRef ID="") {
 static Progress_File1,Progress_File2

  ;ID was passed, that means the functions needs to update an existing progessbar
  If (ID) {
    ;Retrieve every value from the handle
    Loop, Parse, ID, |
      PB%A_Index% := A_LoopField
    ;Invalid ID - GUI number or Progressbar Index is missing
    If (!PB1 || !PB5)
      Return 0
    ;Update the file paths within the id
    ID := PB1 "|" Value "|" PB3 "|" PB4 "|" PB5 "|" PB6 "|" PB7 "|" Background "|" Progress
  }

  ;If existing background picture passed, store or apply it
  If (FileExist(Background))
    If (!ID)
      Progress_File1 := Background
    Else GuiControl, % PB1 ":", % "PBar_" PB1 "_" PB5 "N", % Background
  ;If existing progress picture passed, store or apply it
  If (FileExist(Progress))
    If (!ID)
      Progress_File2 := Progress
    Else GuiControl, % PB1 ":", % "PBar_" PB1 "_" PB5 "R", % Progress

  ;Return either the background or progress, based on passed @Get
  Return (Background = "@Get") ? Progress_File1 : (Progress = "@Get") ? Progress_File2 : (ID) ? 1 : ""
}

;------------------------------------------------------------------------------------------------------------------------------------
;Function:     Progress_SetText
;Parameters:   ID   = The handle returned by Progress_Add
;              Text = The new text to use (Optional)
;Return Value: 0 - Invalid handle
;------------------------------------------------------------------------------------------------------------------------------------
Progress_SetText(ByRef ID,Text="") {
  ;Retrieve every value from the handle
  Loop, Parse, ID, |
    PB%A_Index% := A_LoopField
  ;Break if any of the neccessary values isn't set
  If (PB1 = "" || PB3 = "" || PB4 = "" || PB5 = "" || PB7 = "")
    Return 0
  ;If new text specified, create the new handle
  If (Text != "")
    PB7 := Text,ID := PB1 "|" Value "|" PB3 "|" PB4 "|" PB5 "|" PB6 "|" PB7 "|" PB8 "|" PB9
  ;Replace all "variables"
  If (InStr(PB7,"$")) {
    StringReplace, PB7, PB7, $Position, % PB2, 1
    StringReplace, PB7, PB7, $Range, % SubStr(PB3,InStr(PB3,"-") + 1,StrLen(PB3)), 1
    StringReplace, PB7, PB7, $Percent, % Round(PB2 / PB3 * 100), 1
  }
  ;Update the text
  GuiControl, % PB1 ":", % "PBar_" PB1 "_" PB5 "T", % PB7
}

;------------------------------------------------------------------------------------------------------------------------------------
;Function:     Progress_SetVisibility
;Parameters:   ID      = The handle returned by Progress_Add
;              Visible = Boolean; 0 um die Progressbar zu verstecken, 1 zum anzeigen
;Return Value: 0 - Invalid handle
;------------------------------------------------------------------------------------------------------------------------------------
Progress_SetVisibility(ByRef ID,Visible) {
  ;Retrieve every value from the handle
  Loop, Parse, ID, |
    PB%A_Index% := A_LoopField
  ;Break if any of the neccessary values isn't set
  If (PB1 = "" || PB3 = "" || PB4 = "" || PB5 = "")
    Return 0
  ;Check whether the controls should be hidden or shown
  Visible := (Visible = 0) ? "Hide" : "Show"
  ;Apply the new visibility state
  GuiControl, % PB1 ":" Visible, % "PBar_" PB1 "_" PB5 "N"
  GuiControl, % PB1 ":" Visible, % "PBar_" PB1 "_" PB5 "R"
  GuiControl, % PB1 ":" Visible, % "PBar_" PB1 "_" PB5 "T"
}

;------------------------------------------------------------------------------------------------------------------------------------
;Function:     Progress_Show
;Parameters:   ID = The handle returned by Progress_Add
;Return Value: 0 - Invalid handle
;------------------------------------------------------------------------------------------------------------------------------------
Progress_Show(ByRef ID) {
  Return Progress_SetVisibility(ID,1)
}

;------------------------------------------------------------------------------------------------------------------------------------
;Function:     Progress_Hide
;Parameters:   ID = The handle returned by Progress_Add
;Return Value: 0 - Invalid handle
;------------------------------------------------------------------------------------------------------------------------------------
Progress_Hide(ByRef ID) {
  Return Progress_SetVisibility(ID,0)
}

;------------------------------------------------------------------------------------------------------------------------------------
;Function:     Progress_IsID
;Parameters:   ID = Any value that should be checked
;Return Value: Checks whether the provided ID is an actual and valid Progressbar ID or not
;------------------------------------------------------------------------------------------------------------------------------------
Progress_IsID(ID) {
  ;Check how many separators are within the id
  Loop, Parse, ID, |
    PB%A_Index% := A_LoopField,PB0 := A_Index
  ;Check if it's valid
  Return (PB0 = 9 && (PB1 > 0 && PB1 <= 99) && (PB2+0 != "" && (PB2 >= SubStr(PB3,1,(Pos := InStr(PB3,"-")) - 1) && PB2 <= SubStr(PB3,Pos + 1,StrLen(PB3))))) ? 1 : 0
}

;------------------------------------------------------------------------------------------------------------------------------------
;Function:     Progress_CopyFiles
;Parameters:   /
;Return Value: /
;------------------------------------------------------------------------------------------------------------------------------------
Progress_CopyFiles(Gui,Position,SourceFolder,DestFolder,Pattern="",Sleep=10) {
  ;Create the loop flags
  Wildcard := "*.*",IncludeFolders := 0,Recurse := 1
  Loop, Parse, Pattern, |
    If (InStr("Wildcard,IncludeFolders,Recurse",(PatternName := SubStr(A_LoopField,1,(PatternPos := InStr(A_LoopField,"=")) - 1))))
      %PatternName% := SubStr(A_LoopField,PatternPos + 1,StrLen(A_LoopField))
  ;Stop if either the source folder doesn't exist, or the progressbar can't be created
  hBar := Progress_Add(Gui,Position,"0-1",0,"$Position/$Range")
  If (FileExist(SourceFolder) = "" || hBar = 0)
    Return 0
  ;Retrieve the count of all files within the sourcefolder
  Loop, % SourceFolder "\" Wildcard, % IncludeFolders, % Recurse
    Count := A_Index
  ;Stop if source folder doesn't contain any files
  If (Count = 0 || Count = "")
    Return 0
  ;Update the progressbar range
  Progress_Set(hBar,"0-" Count,1)
  ;Create the destination folder
  FileCreateDir, % DestFolder
  ;Copy all files now
  Loop, % SourceFolder "\" Wildcard, % IncludeFolders, % Recurse
  {
    Progress_Set(hBar,A_Index)
    FileCreateDir, % Folder := DestFolder SubStr(A_LoopFileDir,StrLen(SourceFolder) + 1,StrLen(SourceFolder))
    FileCopy, % A_LoopFileFullPath, % Folder "\" A_LoopFileName
    Sleep, % Sleep
  }
  ;Return the count of copied files
  Return Count
}

Example:
Posted Image

#Include Progress_Lib.ahk

;Download the example images
RequiredFiles := "P-N.png|P-R.png|P-N-2.png|P-R-2.png|P-V-N.png|P-V-R.png"
Loop, Parse, RequiredFiles, |
  If (!FileExist(A_LoopField))
    UrlDownloadToFile, % "http://www.autohotkey.net/~Banane/Images/" A_LoopField, % A_LoopField

GuiCreate:
  ;Create a gui with some fancy options
  Gui, 1:+LastFound -Caption
  Gui, 1:Color, 111111
  WinSet, Region, 0-0 0-0 w395 H100 R9-9

    ;Configure the font
    Gui, 1:Font, cFFFFFF Bold, Arial
    ;Create a slider that will be "connected" with the progressbars
    Gui, 1:Add, Slider, x15 y20 w340 h20 +Range0-4 vSlider gGuiSlider
    ;Select the horizontal progressbar images
    Progress_SetFile("P-N.png","P-R.png")
    ;Create a new progressbar with a range of 0 to 4, Startvalue 0 and a text overlay
    hBar1 := Progress_Add(1,"x15 y50 w340 h15","0-4",0,"$Position/$Range")
    ;Select the vertical progressbar images
    Progress_SetFile("P-V-N.png","P-V-R.png")
    ;Create a new progressbar with a range of 0 to 4, Startvalue 0 and no text overlay
    hBar2 := Progress_Add(1,"x365 y20 w15 h45","0-4",0,"",1)

    Gui, Add, Text, x115 y70 w140 h15 , Graphical Progressbar...

    ;Create some text controls that contain info on the progressbars value
    Gui, Add, Text, x300 y70 w50 h15 vText1 +Right, % Progress_Get(hBar1,2) "%"
    Gui, Add, Text, x15 y70 w75 h15 vText2, % Progress_Get(hBar1,1) "/" Progress_Get(hBar1,3)

  Gui, 1:Show, w395 h100, Progress
  Return

GuiSlider:
  GuiControlGet, Slider
  ;Set the progressbar position to the sliders value
  Progress_Set(hBar1,Slider),Progress_Set(hBar2,Slider)
  GoSub, GuiUpdate
  Return

GuiUpdate:
  ;Update the percent text
  GuiControl, 1:, Text1, % Progress_Get(hBar1,2) "%"
  ;Update the external value text (Position/Range)
  GuiControl, 1:, Text2, % Progress_Get(hBar1,1) "/" Progress_Get(hBar1,3)
  Return

GuiClose:
  ExitApp

#IfWinActive, Progress

;Hide the progressbars when F1 is pressed
~F1::Progress_Hide(hBar1),Progress_Hide(hBar2)

;Show the progressbars when F2 is pressed
~F2::Progress_Show(hBar1),Progress_Show(hBar2)

;Show the progressbars visibility state when F3 is pressed
~F3::MsgBox % "hBar1: " Progress_Get(hBar1,4) "`nhBar2: " Progress_Get(hBar2,4)

;Change the internal text of the first progressbar to Hello World when F4 is pressed
~F4::Progress_SetText(hBar1,"Hello World")

;Change the slider and progressbar range from 0-4 to 0-100 when F5 is pressed
~F5::
  GuiControl, +Range0-100, Slider
  Progress_Set(hBar1,"0-100",1),Progress_Set(hBar2,"0-100",1)
  GoSub, GuiUpdate
  Return

;Set the progressbars value from 0 up to their range when F6 is pressed
~F6::
  Progress_Set(hBar1,0),Progress_Set(hBar2,0)
  Loop, % Progress_Get(hBar1,3) {
    Progress_Set(hBar1,A_Index),Progress_Set(hBar2,A_Index)
    GoSub, GuiUpdate
    Sleep, 5
  }
  Return

;Change the progressbars images
~F7::
  Progress_SetFile("P-N-2.png","P-R-2.png",hBar1)
  Return

;Show the progressbar images when pressed
~F8::MsgBox % "Background: " Progress_Get(hBar1,6) "`nProgress:  " Progress_Get(hBar1,7)

Changelog:
18.1.2011 - Initial Release
15.2.2011 - Progress_IsID() and Progress_CopyFiles() added, Progress_SetFile() and Progress_Get() improved.

#2 Lucid_Method

Lucid_Method
  • Members
  • 146 posts

Posted 23 January 2011 - 03:30 AM

Nice job :-)

#3 codybear

codybear
  • Members
  • 589 posts

Posted 23 January 2011 - 04:02 AM

I'd have to agree, this looks very promising.

#4 bmoore45

bmoore45
  • Members
  • 273 posts

Posted 17 November 2011 - 09:27 PM

bump to say thanks, this is super simple and easy to work with!

#5 jleslie48

jleslie48
  • Members
  • 137 posts

Posted 14 February 2012 - 10:43 PM

This looks great and it works great too. Thank you so much.

I do have a how do I? question though.

I would like to change the image based on the value, I'm trying to make a pressure Gauge, so when the percent of the progress is under 75%, its one image (green tones) and when it gets above 75% to 90% switch to a new image that has yellow tones, and then finally above 90% switch to one that as red tones. I don't see looking at the progress_lib.ahk, how the progress_setfile can be used/updated to allow for changes.

For example in the example the F5 switches to 0-100, and then the F6 marches from 0-100. How do I address the individual progress elements (hbar1 and hbar2) to change the images that are shown?

how can I make up an Progress_updatefile(handle, file1, file2) function so the functionality is something like this:


;Set the progressbars value from 0 up to their range when F6 is pressed
~F6::
  Progress_Set(hBar1,0),Progress_Set(hBar2,0)
  Loop, % Progress_Get(hBar1,3) {
    slider2 := 100-A_index
    Progress_Set(hBar1,A_Index)

    if a_index > 90
            {
            progress_updatefile(hbar2, "red_on.png","red_off.png")
            } 
     else if a_index >75 {
            progress_updatefile(hbar2, "yellow_on.png","yellow_off.png")
            }
     else {
            progress_updatefile(hbar2, "green_on.png","green_off.png")
            }
   Progress_Set(hBar2,slider2)

    
     GoSub, GuiUpdate
    Sleep, 5
    }  ; Loop
  Return    ; F6 



#6 Banane

Banane
  • Members
  • 46 posts

Posted 14 February 2012 - 11:48 PM

how the progress_setfile can be used/updated to allow for changes.

Thanks for the heads-up. In the previous version, this function was only used to set the image files for all following progressbars, not to change them dynamically during run-time.

After thinking about this, I realized that it didn't make all that much sense to have this restriction - so there's now the possiblity to specify an progressbar ID as the third parameter to allow for this. :)

Updated the example to demonstrate the usage (F7 is used for the dynamic image changing).

#7 jleslie48

jleslie48
  • Members
  • 137 posts

Posted 15 February 2012 - 12:56 AM

how the progress_setfile can be used/updated to allow for changes.

Thanks for the heads-up. In the previous version, this function was only used to set the image files for all following progressbars, not to change them dynamically during run-time.

After thinking about this, I realized that it didn't make all that much sense to have this restriction - so there's now the possiblity to specify an progressbar ID as the third parameter to allow for this. :)

Updated the example to demonstrate the usage (F7 is used for the dynamic image changing).


WoW!!!! That's what I call service! Works like a charm. this is just terrific.

So I'm trying to reverse engineer your code, progress_setfile now has 3 functions built into it,

1) setting the image files for future calls to progress_add
2) the new functionality to update the images of a particular progress bar identified by its handle as a third parameter,
3) I see a bunch of calls to progress_setfile to return images within the progress_lib.ahk,

Now being a newbie to ahk, you've got me very intrigued by your use of array elements and loops to store the elements of the handle (I dare say you made up some kind of structure) would you care to explain how that loop, parse, ID, ...

part works,
and how tthe IF(!ID) statements work,

I see that if there is no ID, you set the progress_file[1&2] but that else is a real head scratcher...

Thanks again, I'm very impressed with your work.

- Jon

#8 Banane

Banane
  • Members
  • 46 posts

Posted 15 February 2012 - 02:40 PM

progress_setfile now has 3 functions built into it

Spot on, you're correct! :)

would you care to explain how that loop, parse, ID, ... part works

Surely!

Since there are multiple values for each progressbar, that have to be stored, I decided to put all of them
into "list" - that is nothing more than a string, constisting of all kinds of values, separated by a "|" in this case.

So, whenever a function wants to access a progressbar, we have to pass this string into it, so that the function can retrieve all invidual values, required to achieve it's task.

In this case, the list consists of the following values:
[*:hn8y5o3c]Number of the GUI that contains the progressbar
[*:hn8y5o3c]The current numerical value of the progressbar
[*:hn8y5o3c]The highest possible numerical value
[*:hn8y5o3c]Complete width of the progressbar control (to determine how wide it should be allowed to become)
[*:hn8y5o3c]Progressbar index (first progressbar has a 1, second as a 2, etc.)
[*:hn8y5o3c]The progressbar direction (either 0 for horizontal or 1 for vertical)
[*:hn8y5o3c]Current text of the progressbar controlSo, the handle could look like this:

"1|50|100|250|1|0|"

What the other then do is, they parse the handle to retrieve every invidual value in a separate variable - so that they can easily access and work with those values.

As for the "Else" branches in Progress_SetFile(), they retrieve the gui number and recreate the progressbar controls variables by using the values from it's handle

PB1 = GUI Number, PB5 = Progressbar Index

#9 jleslie48

jleslie48
  • Members
  • 137 posts

Posted 15 February 2012 - 03:21 PM

wonderful description. you should cut and paste in its entirety in the header section of the progress_lib.ahk along with the triple functionality description of the setfile command. Your list usage is great, I'm gonna keep that in my pocket for future development.

However, the List is not complete, where are the files associated with the individual progressbars located, PB1 through PB7 isn't enough for the complete graphical gui bar. is there a pb8 and pb9?

#10 Banane

Banane
  • Members
  • 46 posts

Posted 15 February 2012 - 05:07 PM

Well, the list was complete actually - I just didn't think of adding the image filepaths into it so far, have been added now. :)