Page 1 of 3

FlatButtonEx Crossplattform

Posted: Fri Feb 22, 2013 4:15 pm
by ts-soft
FlatButtonEx.pbi

A crossplattform Class for Flatbuttons

Features:
- Text only Button
- Image only Button
- Mixed Button (Image left and Text right)
- Autoresize Image
- All Features of other Buttons, but without Toogle-Support
- Highlights on Mouseover with Hotcolor
- Sunken on press
- Gradients
- Focusrectangle
- Shortcuts

IncludeFile:

Code: Select all

;======================================================================
; Library:         FlatButtonEx.pbi
;
; Author:          Thomas (ts-soft) Schulz
; Date:            Feb 22, 2013
; Version:         1.9.1
; Target Compiler: PureBasic 5.1+
; Target OS:       Windows, Linux, MacOS
; License:         Free, unrestricted, no warranty whatsoever
;                  Use at your own risk
;======================================================================
; History
; Version 1.9.1
; fixed a flickering bug on mousemove
;
; Version 1.9 (Feb 26, 2013)
; added: Icon resizing is full supported (windows only)
; optimized code
;
; Version 1.8.4 (Feb 25, 2013)
; fixed a bug with right bottom pixel
;
; Version 1.8.3 (Feb 25, 2013)
; added Icon-Support for Windows
; Attention: Icons can't be resized!
;
; Version 1.8.2 (Feb 25, 2013)
; added default systemcolor for MacOSX, thx to wilbert
;
; Version 1.8.1 (Feb 25, 2013)
; added Support for texthotcolor
; new colorconstant: #FlatButtonEx_Color_TextHotColor

; Version 1.8 (Feb 25, 2013)
; added Gradient-Type: SetGradientType([Type.i[, customcallback.i]])
; with types:
;   #FlatButtonEx_Gradient_Linear (default)
;   #FlatButtonEx_Gradient_Boxed
;   #FlatButtonEx_Gradient_Custom (requires customcallback)
;
; Version 1.7 (Feb 24, 2013)
; added Gradient-Support
; SetGradient() and SetHotGradient()
;
; Version 1.6 (Feb 24, 2013)
; changed GetSpaceSupport() to GetShortCut()
; changed SetSpaceSupport() to SetShortCut(), default is #PB_Shortcut_Space, set to 0 for none shortcutsupport
; added default systemcolor for Linux, thx to uwekel
;
; Version 1.5 (Feb 24, 2013)
; added GetSpaceSupport() and SetSpaceSupport() methodes, to set or get this on runtime
; added GetCursor(), SetCursor() and SetCustomCursor methodes
; some Setter methodes return #TRUE on access
; some codeoptimation and bughunting
;
; Version 1.4 (Feb 23, 2013)
; fixed a bug with SupportKeyboard flag
; optimized the code
;
; Version 1.3 (Feb 23, 2013)
; added support for focusrectangle
; added support for spacebar to click
; changed Example to reflect the new features
;
; Version 1.2
; fixed bug with pressed button outside gadget
;
; Version 1.1
; fixed a memoryleak with images!

Declare.i FlatButtonEx_Update(*this, EventType = #PB_EventType_MouseLeave)
Declare.l FlatButtonEx_GetGadgetColor(Gadget.i, Type.i, State.i = 0)

Enumeration ; colortype
  #FlatButtonEx_Color_TextColor
  #FlatButtonEx_Color_TextHotColor
  #FlatButtonEx_Color_HotColor
  #FlatButtonEx_Color_BackColor
EndEnumeration

Enumeration ; gradienttype
  #FlatButtonEx_Gradient_Linear
  #FlatButtonEx_Gradient_Boxed
  #FlatButtonEx_Gradient_Custom
EndEnumeration

Enumeration ;gtk colortypes
  #GtkGadgetColorBase
  #GtkGadgetColorBg
  #GtkGadgetColorDark
  #GtkGadgetColorFg
  #GtkGadgetColorLight
  #GtkGadgetColorText
EndEnumeration

Enumeration ; gtk states
  #GtkStateNormal
  #GtkStateActive
  #GtkStatePrelight
  #GtkStateSelected
  #GtkStateIntensitive
EndEnumeration

Interface FlatButtonEx
  ; Getter Methodes
  GetID.i()
  GetX.i(Mode.i = #PB_Gadget_ContainerCoordinate)
  GetY.i(Mode.i = #PB_Gadget_ContainerCoordinate)
  GetWidth.i()
  GetHeight.i()
  GetData.i()
  GetColor.l(Type.i)
  GetText.s()
  GetImage.i()
  GetSizedImage.i()
  GetShortCut.i()
  GetCursor.i()
 
  ; Setter Methodes
  SetFont.i(Font.i = -1)
  SetColor.i(Type.i, Color.l)
  SetText.i(Text.s = "")
  SetImage.i(Image.i = -1)
  SetData.i(Value.i)
  SetToolTip.i(Text.s = "")
  SetShortCut.i(ShortCut.i = #PB_Shortcut_Space)
  SetCursor(Cursor.i = #PB_Cursor_Default)
  SetCustomCursor(Cursor.i)
  SetGradient(backcolor.l = -1, forecolor.l = -1)
  SetHotGradient(backcolor.l = -1, forecolor.l = -1)
  SetGradientType(Type.i = #FlatButtonEx_Gradient_Linear, customcallback.i = 0)
 
  ; Other Methodes
  Update(EventType.i = #PB_EventType_MouseLeave)
  Resize(x.i, y.i, w.i, h.i)
  Disable(State.i = #True)
  Hide(State.i = #True)
  Free()
EndInterface

Structure FlatButtonEx_ClassTemplate
  *vTable
  ID.i
  x.i
  y.i
  w.i
  h.i
  inactive.i
  text.s
  textcolor.l
  texthotcolor.l
  hotcolor.l
  backcolor.l
  gradientbackcolor.l
  gradientforecolor.l
  gradienthotbackcolor.l
  gradienthotforecolor.l
  gradienttype.i
  customcallback.i
  Image.i
  sizedImage.i
  IsIco.i
  Font.i
  ShortCut.i
EndStructure

Procedure New_FlatButtonEx(x.i, y.i, w.i, h.i, DrawFocus.i = #False, ShortCut.i = #PB_Shortcut_Space)
  Protected *object.FlatButtonEx_ClassTemplate, Flag.i = 0
 
  If DrawFocus : Flag | #PB_Canvas_DrawFocus : EndIf
 
  *object = AllocateMemory(SizeOf(FlatButtonEx_ClassTemplate))
  If *object
    With *object
      \vTable = ?vTable_FlatButtonEx
      \ID = CanvasGadget(#PB_Any, x, y, w, h, Flag)
      \x = x
      \y = y
      \w = w
      \h = h
      \text = ""
      \Image = -1
      \textcolor = 0
      \texthotcolor = -1
      \backcolor = FlatButtonEx_GetGadgetColor(\ID, #GtkGadgetColorBg)
      \hotcolor = FlatButtonEx_GetGadgetColor(\ID, #GtkGadgetColorLight)
      \gradientbackcolor = -1
      \gradientforecolor = -1
      \gradienthotbackcolor - 1
      \gradienthotforecolor = -1
      \gradienttype = #FlatButtonEx_Gradient_Linear
      \customcallback = 0
      \Image = -1
      \sizedImage = -1
      \Font = -1
      \ShortCut = ShortCut
    EndWith
    FlatButtonEx_Update(*object)
    ProcedureReturn *object
  EndIf
EndProcedure

Procedure.i FlatButtonEx_GetID(*this.FlatButtonEx_ClassTemplate)
  If *this And IsGadget(*this\ID)
    ProcedureReturn *this\ID
  EndIf
EndProcedure

Procedure.i FlatButtonEx_GetX(*this.FlatButtonEx_ClassTemplate, Mode.i = #PB_Gadget_ContainerCoordinate)
  If *this And IsGadget(*this\ID)
    ProcedureReturn GadgetX(*this\ID, Mode)
  EndIf
EndProcedure

Procedure.i FlatButtonEx_GetY(*this.FlatButtonEx_ClassTemplate, Mode.i = #PB_Gadget_ContainerCoordinate)
  If *this And IsGadget(*this\ID)
    ProcedureReturn GadgetY(*this\ID, Mode)
  EndIf
EndProcedure

Procedure.i FlatButtonEx_GetWidth(*this.FlatButtonEx_ClassTemplate)
  If *this And IsGadget(*this\ID)
    ProcedureReturn GadgetWidth(*this\ID)
  EndIf
EndProcedure

Procedure.i FlatButtonEx_GetHeight(*this.FlatButtonEx_ClassTemplate)
  If *this And IsGadget(*this\ID)
    ProcedureReturn GadgetHeight(*this\ID)
  EndIf
EndProcedure

Procedure.i FlatButtonEx_GetData(*this.FlatButtonEx_ClassTemplate)
  If *this And IsGadget(*this\ID)
    ProcedureReturn GetGadgetData(*this\ID)
  EndIf
EndProcedure

Procedure.l FlatButtonEx_GetColor(*this.FlatButtonEx_ClassTemplate, Type.i)
  If *this And IsGadget(*this\ID)
    Select Type
      Case #FlatButtonEx_Color_TextColor
        ProcedureReturn *this\textcolor
      Case #FlatButtonEx_Color_TextHotColor
        ProcedureReturn *this\texthotcolor
      Case #FlatButtonEx_Color_HotColor
        ProcedureReturn *this\hotcolor
      Case #FlatButtonEx_Color_BackColor
        ProcedureReturn *this\backcolor
    EndSelect
  EndIf
EndProcedure

Procedure.s FlatButtonEx_GetText(*this.FlatButtonEx_ClassTemplate)
  If *this And IsGadget(*this\ID)
    ProcedureReturn *this\text
  EndIf
EndProcedure

Procedure.i FlatButtonEx_GetImage(*this.FlatButtonEx_ClassTemplate)
  If *this And IsGadget(*this\ID)
    ProcedureReturn *this\Image
  EndIf
EndProcedure

Procedure.i FlatButtonEx_GetSizedImage(*this.FlatButtonEx_ClassTemplate)
  If *this And IsGadget(*this\ID)
    ProcedureReturn *this\sizedImage
  EndIf
EndProcedure

Procedure.i FlatButtonEx_GetShortCut(*this.FlatButtonEx_ClassTemplate)
  If *this And IsGadget(*this\ID)
    ProcedureReturn *this\ShortCut
  EndIf
EndProcedure

Procedure.i FlatButtonEx_GetCursor(*this.FlatButtonEx_ClassTemplate)
  Protected result.i
 
  If *this And IsGadget(*this\ID)
    With *this
      result = GetGadgetAttribute(\ID, #PB_Canvas_Cursor)
      If result = -1
        result = GetGadgetAttribute(\ID, #PB_Canvas_CustomCursor)
      EndIf
      ProcedureReturn result
    EndWith
  EndIf
EndProcedure

Procedure.i FlatButtonEx_SetFont(*this.FlatButtonEx_ClassTemplate, Font.i = -1)
  If *this And IsGadget(*this\ID)
    If IsFont(Font)
      *this\Font = Font
    Else
      *this\Font = -1
    EndIf
    FlatButtonEx_Update(*this)
    ProcedureReturn #True
  EndIf
EndProcedure

Procedure.i FlatButtonEx_SetColor(*this.FlatButtonEx_ClassTemplate, Type.i, Color.i)
  If *this And IsGadget(*this\ID)
    With *this
      Select Type
        Case #FlatButtonEx_Color_TextColor
          \textcolor = Color
        Case #FlatButtonEx_Color_TextHotColor
          \texthotcolor = Color
        Case #FlatButtonEx_Color_HotColor
          \hotcolor = Color
        Case #FlatButtonEx_Color_BackColor
          \backcolor = Color
      EndSelect
    EndWith
    FlatButtonEx_Update(*this)
    ProcedureReturn #True
  EndIf
EndProcedure

Procedure.i FlatButtonEx_SetText(*this.FlatButtonEx_ClassTemplate, Text.s = "")
  If *this And IsGadget(*this\ID)
    *this\text = Text
    FlatButtonEx_Update(*this)
    ProcedureReturn #True
  EndIf
EndProcedure

Procedure.i FlatButtonEx_SetImage(*this.FlatButtonEx_ClassTemplate, Image.i = -1)
  Protected img.i
  
  If *this And IsGadget(*this\ID)
    With *this
      If IsImage(\sizedImage)
        FreeImage(\sizedImage)
        \sizedImage = -1
      EndIf
      If \IsIco
        If IsImage(\Image) : FreeImage(\Image) : EndIf
      EndIf
      \IsIco = #False
      If IsImage(Image)
        If ImageFormat(Image) = #PB_ImagePlugin_ICON
          img = CreateImage(#PB_Any, ImageWidth(Image), ImageHeight(Image), 32)
          If img
            StartDrawing(ImageOutput(img))
              DrawingMode(#PB_2DDrawing_AllChannels)
              DrawImage(ImageID(Image), 0, 0)
            StopDrawing()
            Image = img
            \IsIco = #True
          EndIf
        EndIf
        \Image = Image
      Else
        \Image = -1
      EndIf
    EndWith
    FlatButtonEx_Update(*this)
    ProcedureReturn #True
  EndIf
EndProcedure

Procedure.i FlatButtonEx_SetData(*this.FlatButtonEx_ClassTemplate, Value.i)
  If *this And IsGadget(*this\ID)
    SetGadgetData(*this\ID, Value)
    ProcedureReturn #True
  EndIf
EndProcedure

Procedure.i FlatButtonEx_SetToolTip(*this.FlatButtonEx_ClassTemplate, Text.s = "")
  If *this And IsGadget(*this\ID)
    GadgetToolTip(*this\ID, Text)
    ProcedureReturn #True
  EndIf
EndProcedure

Procedure.i FlatButtonEx_SetShortCut(*this.FlatButtonEx_ClassTemplate, ShortCut.i = #PB_Shortcut_Space)
  If *this And IsGadget(*this\ID)
    *this\ShortCut = ShortCut
    ProcedureReturn #True
  EndIf
EndProcedure

Procedure FlatButtonEx_SetCursor(*this.FlatButtonEx_ClassTemplate, Cursor.i = #PB_Cursor_Default)
  If *this And IsGadget(*this\ID)
    SetGadgetAttribute(*this\ID, #PB_Canvas_Cursor, Cursor)
  EndIf
EndProcedure

Procedure FlatButtonEx_SetCustomCursor(*this.FlatButtonEx_ClassTemplate, Cursor.i)
  If *this And IsGadget(*this\ID)
    SetGadgetAttribute(*this\ID, #PB_Canvas_CustomCursor, Cursor)
  EndIf
EndProcedure

Procedure FlatButtonEx_SetGradient(*this.FlatButtonEx_ClassTemplate, backcolor.l = -1, forecolor.l = -1)
  If *this And IsGadget(*this\ID)
    With *this
      \gradientbackcolor = backcolor
      \gradientforecolor = forecolor
      FlatButtonEx_Update(*this)
    EndWith
  EndIf
EndProcedure

Procedure FlatButtonEx_SetHotGradient(*this.FlatButtonEx_ClassTemplate, backcolor.l = -1, forecolor.l = -1)
  If *this And IsGadget(*this\ID)
    With *this
      \gradienthotbackcolor = backcolor
      \gradienthotforecolor = forecolor
      FlatButtonEx_Update(*this)
    EndWith
  EndIf
EndProcedure

Procedure FlatButtonEx_SetGradientType(*this.FlatButtonEx_ClassTemplate, Type.i = #FlatButtonEx_Gradient_Linear, customcallback.i = 0)
  If *this And IsGadget(*this\ID)
    *this\gradienttype = Type
    *this\customcallback = customcallback
    FlatButtonEx_Update(*this)
  EndIf
EndProcedure

Procedure.l FlatButtonEx_GetGadgetColor(Gadget.i, Type.i, State.i = 0)
  ; by uwekel
  ; see: http://www.purebasic.fr/english/viewtopic.php?p=405822#p405822
  ; OSX part by wilbert
  ; see: http://www.purebasic.fr/english/viewtopic.php?p=405916#p405916
 
  CompilerSelect #PB_Compiler_OS
  CompilerCase #PB_OS_Linux
  ;returns a widget color
  Protected *style.GtkStyle, *color.GdkColor
  ;get widget style
  *style = gtk_widget_get_style_(GadgetID(Gadget))
  ;return color according type and state
  Select Type
    Case #GtkGadgetColorBase
      *color = *style\base[State]
    Case #GtkGadgetColorBg
      *color = *style\bg[State]
    Case #GtkGadgetColorDark
      *color = *style\dark[State]
    Case #GtkGadgetColorFg
      *color = *style\fg[State]
    Case #GtkGadgetColorLight
      *color = *style\light[State]
    Case #GtkGadgetColorText
      *color = *style\text[State]
  EndSelect
  ;return color value
  ProcedureReturn RGB(*color\red >> 8, *color\green >> 8, *color\blue >> 8)
  CompilerCase #PB_OS_Windows
  Select Type
    Case #GtkGadgetColorBg, #GtkGadgetColorBase
      If State = #GtkStateSelected
        ProcedureReturn GetSysColor_(#COLOR_HIGHLIGHT)
      Else
        ProcedureReturn GetSysColor_(#COLOR_WINDOW)
      EndIf
    Case #GtkGadgetColorFg, #GtkGadgetColorText
      If State = #GtkStateSelected
        ProcedureReturn GetSysColor_(#COLOR_HIGHLIGHTTEXT)
      Else
        ProcedureReturn GetSysColor_(#COLOR_WINDOWTEXT)
      EndIf
    Case #GtkGadgetColorDark
      ProcedureReturn GetSysColor_(#COLOR_BTNSHADOW)
    Case #GtkGadgetColorLight
      ProcedureReturn GetSysColor_(#COLOR_3DLIGHT)
  EndSelect
  CompilerCase #PB_OS_MacOS
  Protected ColorName.s, Color.i
  Protected.CGFloat R, G, B, A
  Select Type
    Case #GtkGadgetColorBg
      ColorName = "controlBackgroundColor"
    Case #GtkGadgetColorLight
      ColorName = "controlHighlightColor"
  EndSelect
  Color = CocoaMessage(0, 0, "NSColor " + ColorName)
  If Color : Color = CocoaMessage(0, Color, "colorUsingColorSpaceName:$", @"NSDeviceRGBColorSpace") : EndIf
  If Color : CocoaMessage(0, Color, "getRed:", @R, "green:", @G, "blue:", @B, "alpha:", @A) : EndIf
  ProcedureReturn RGBA(R * 255, G * 255, B * 255, A * 255)
  CompilerEndSelect
EndProcedure

CompilerIf Not Defined(IsMouseOverGadget, #PB_Procedure)
Procedure.i IsMouseOverGadget(window.i, gadget.i)
  If (WindowMouseX(window) >= GadgetX(gadget)) And (WindowMouseX(window) <= (GadgetX(gadget) + GadgetWidth(gadget)))
    If (WindowMouseY(window) >= GadgetY(gadget)) And (WindowMouseY(window) <= (GadgetY(gadget) + GadgetHeight(gadget)))
      ProcedureReturn #True
    EndIf
  EndIf
EndProcedure
CompilerEndIf

Macro _FlatButtonExGradient_
  If \gradientbackcolor <> -1 And \gradientforecolor <> -1
    DrawingMode(#PB_2DDrawing_Gradient)
    BackColor(\gradientbackcolor)
    FrontColor(\gradientforecolor)
    Select \gradienttype
      Case #FlatButtonEx_Gradient_Boxed
        BoxedGradient(0, 0, \w -1, \h -1)
      Case #FlatButtonEx_Gradient_Custom
        CustomGradient(\customcallback)
      Default
        LinearGradient(0, \h -1, \w -1, 0)
    EndSelect
    Box(0, 0, \w -1, \h -1)
    DrawingMode(#PB_2DDrawing_Transparent)
  EndIf
EndMacro

Macro _FlatButtonExDrawSunken_
  Box(0, 0, \w -1, \h -1, \backcolor)
  _FlatButtonExGradient_
  Line(0, 0, \w -1, 1, RGB(128, 128, 128))
  Line(0, \h- 1, \w -1, 1, RGB(255, 255, 255))
  Line(0, 0, 1, \h -1, RGB(128, 128, 128))
  Line(\w -1, 0, 1, \h, RGB(255, 255, 255))
  If \Font <> -1
    DrawingFont(FontID(\Font))
  EndIf
  If \Image <> -1
    If IsImage(\sizedImage) And ImageHeight(\sizedImage) = GadgetHeight(\ID) - 10
      If \text = ""
        If ImageWidth(\sizedImage) = GadgetWidth(\ID) - 10
          DrawAlphaImage(ImageID(\sizedImage), 6, GadgetHeight(\ID) - ImageHeight(\sizedImage) - 4)
        Else
          If \sizedImage And IsImage(\sizedImage) : FreeImage(\sizedImage) : EndIf
          img = CopyImage(\Image, #PB_Any)
          ResizeImage(img, GadgetWidth(\ID) - 10, GadgetHeight(\ID) - 10)
          DrawAlphaImage(ImageID(img), 6, GadgetHeight(\ID) - ImageHeight(img) - 4)
          \sizedImage = img
        EndIf
      Else
        If ImageWidth(\sizedImage) = GadgetWidth(\ID) - 10
          FreeImage(\sizedImage)
          img = CopyImage(\Image, #PB_Any)
          ResizeImage(img, GadgetHeight(\ID) - 10, GadgetHeight(\ID) - 10)
          \sizedImage = img
        EndIf
        DrawAlphaImage(ImageID(\sizedImage), 6, GadgetHeight(\ID) - ImageHeight(\sizedImage) - 4)
        DrawText(ImageWidth(\sizedImage) + 11, (GadgetHeight(\ID) - TextHeight(\text)) / 2 + 1, \text, \textcolor)
      EndIf
    Else
      If \text = ""
        img = CopyImage(\Image, #PB_Any)
        ResizeImage(img, GadgetWidth(\ID) - 10, GadgetHeight(\ID) - 10)
        DrawAlphaImage(ImageID(img), 6, GadgetHeight(\ID) - ImageHeight(img) - 4)
        \sizedImage = img     
      Else
        If \sizedImage And IsImage(\sizedImage) : FreeImage(\sizedImage) : EndIf
        img = CopyImage(\Image, #PB_Any)
        ResizeImage(img, GadgetHeight(\ID) - 10, GadgetHeight(\ID) - 10)
        DrawAlphaImage(ImageID(img), 6, GadgetHeight(\ID) - ImageHeight(img) - 4)
        DrawText(ImageWidth(img) + 11, (GadgetHeight(\ID) - TextHeight(\text)) / 2 + 1, \text, \textcolor)
        \sizedImage = img
      EndIf
    EndIf
  Else
    DrawText((GadgetWidth(\ID) - TextWidth(\text)) / 2 + 1, (GadgetHeight(\ID) - TextHeight(\text)) / 2 + 1, \text, \textcolor)
  EndIf
EndMacro

Macro _FlatButtonExDraw_
  If \Font <> -1
    DrawingFont(FontID(\Font))
  EndIf
  If \Image <> -1
    If IsImage(\sizedImage) And ImageHeight(\sizedImage) = GadgetHeight(\ID) - 10
      If \text = ""
        If ImageWidth(\sizedImage) = GadgetWidth(\ID) - 10
          DrawAlphaImage(ImageID(\sizedImage), 5, GadgetHeight(\ID) - ImageHeight(\sizedImage) - 5)
        Else
          If \sizedImage And IsImage(\sizedImage) : FreeImage(\sizedImage) : EndIf
          img = CopyImage(\Image, #PB_Any)
          ResizeImage(img, GadgetWidth(\ID) - 10, GadgetHeight(\ID) - 10)
          DrawAlphaImage(ImageID(img), 5, GadgetHeight(\ID) - ImageHeight(img) - 5)
          \sizedImage = img
        EndIf
      Else
        If ImageWidth(\sizedImage) = GadgetWidth(\ID) - 10 And ImageFormat(\sizedImage) <> #PB_ImagePlugin_ICON
          FreeImage(\sizedImage)
          img = CopyImage(\Image, #PB_Any)
          ResizeImage(img, GadgetHeight(\ID) - 10, GadgetHeight(\ID) - 10)
          \sizedImage = img
        EndIf
        DrawAlphaImage(ImageID(\sizedImage), 5, GadgetHeight(\ID) - ImageHeight(\sizedImage) - 5)
        If hot And \texthotcolor <> -1
          DrawText(ImageWidth(\sizedImage) + 10, (GadgetHeight(\ID) - TextHeight(\text)) / 2, \text, \texthotcolor)
        Else
          DrawText(ImageWidth(\sizedImage) + 10, (GadgetHeight(\ID) - TextHeight(\text)) / 2, \text, \textcolor)
        EndIf
      EndIf
    Else
      If \text = ""
        If \sizedImage And IsImage(\sizedImage) : FreeImage(\sizedImage) : EndIf
        img = CopyImage(\Image, #PB_Any)
        ResizeImage(img, GadgetWidth(\ID) - 10, GadgetHeight(\ID) - 10)
        DrawAlphaImage(ImageID(img), 5, GadgetHeight(\ID) - ImageHeight(img) - 5)
        \sizedImage = img     
      Else
        If \sizedImage And IsImage(\sizedImage) : FreeImage(\sizedImage) : EndIf
        img = CopyImage(\Image, #PB_Any)
        ResizeImage(img, GadgetHeight(\ID) - 10, GadgetHeight(\ID) - 10)
        DrawAlphaImage(ImageID(img), 5, GadgetHeight(\ID) - ImageHeight(img) - 5)
        If hot And \texthotcolor <> -1
          DrawText(ImageWidth(\sizedImage) + 10, (GadgetHeight(\ID) - TextHeight(\text)) / 2, \text, \texthotcolor)
        Else
          DrawText(ImageWidth(img) + 10, (GadgetHeight(\ID) - TextHeight(\text)) / 2, \text, \textcolor)
        EndIf
        \sizedImage = img
      EndIf
    EndIf
  Else
    If hot And \texthotcolor <> -1
      DrawText((GadgetWidth(\ID) - TextWidth(\text)) / 2, (GadgetHeight(\ID) - TextHeight(\text)) / 2, \text, \texthotcolor)
    Else
      DrawText((GadgetWidth(\ID) - TextWidth(\text)) / 2, (GadgetHeight(\ID) - TextHeight(\text)) / 2, \text, \textcolor)
    EndIf
  EndIf
EndMacro

Procedure FlatButtonEx_Update(*this.FlatButtonEx_ClassTemplate, EventType.i = #PB_EventType_MouseLeave)
  Protected img, hot = 0
 
  If *this And IsGadget(*this\ID)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Linux
        If GadgetWidth(*this\ID) > 10 And GadgetHeight(*this\ID) > 10 And EventType <> #PB_EventType_MouseMove
      CompilerDefault
        If GadgetWidth(*this\ID) > 10 And GadgetHeight(*this\ID) > 10
    CompilerEndSelect
      With *this
        StartDrawing(CanvasOutput(\ID))
          DrawingMode(#PB_2DDrawing_Transparent)
          If \inactive
            Box(0, 0, \w -1, \h -1, \backcolor)
            _FlatButtonExGradient_
            Line(0, 0, \w -1, 1, RGB(128, 128, 128))
            Line(0, \h -1, \w -1, 1, RGB(128, 128, 128))
            Line(0, 0, 1, \h -1, RGB(128, 128, 128))
            Line(\w -1, 0, 1, \h, RGB(128, 128, 128))
            _FlatButtonExDraw_
          ElseIf IsWindow(GetActiveWindow()) And EventType = #PB_EventType_KeyDown
            If GetGadgetAttribute(\ID, #PB_Canvas_Key) = \ShortCut
              _FlatButtonExDrawSunken_
              While WindowEvent() : Wend
            EndIf
           
          ElseIf IsWindow(GetActiveWindow()) And EventType = #PB_EventType_KeyUp
            If GetGadgetAttribute(\ID, #PB_Canvas_Key) = \ShortCut
              Box(0, 0, \w - 1, \h -1, \backcolor)
              _FlatButtonExGradient_
              Line(0, 0, \w -1, 1, RGB(128, 128, 128))
              Line(0, \h -1, \w -1, 1, RGB(128, 128, 128))
              Line(0, 0, 1, \h -1, RGB(128, 128, 128))
              Line(\w -1, 0, 1, \h, RGB(128, 128, 128))
              _FlatButtonExDraw_
              PostEvent(#PB_Event_Gadget, GetActiveWindow(), \ID, #PB_EventType_LeftClick)
            EndIf
 
          ElseIf IsWindow(GetActiveWindow()) And Not IsMouseOverGadget(GetActiveWindow(), \ID)
            Box(0, 0, \w -1, \h -1, \backcolor)
            _FlatButtonExGradient_
            Line(0, 0, \w -1, 1, RGB(128, 128, 128))
            Line(0, \h -1, \w -1, 1, RGB(128, 128, 128))
            Line(0, 0, 1, \h -1, RGB(128, 128, 128))
            Line(\w -1, 0, 1, \h, RGB(128, 128, 128))
            _FlatButtonExDraw_
            WindowEvent()           
          Else
            Select EventType
              Case #PB_EventType_MouseEnter, #PB_EventType_LeftButtonUp
                hot = #True
                Box(0, 0, \w - 1, \h -1, \backcolor)
                _FlatButtonExGradient_
                Line(0, 0, \w -1, 1, RGB(128, 128, 128))
                Line(0, \h -1, \w -1, 1, RGB(128, 128, 128))
                Line(0, 0, 1, \h -1, RGB(128, 128, 128))
                Line(\w -1, 0, 1, \h, RGB(128, 128, 128))
                Box(2, 2, \w -3, \h -3, \hotcolor)
                If \gradienthotbackcolor <> -1 And \gradienthotforecolor <> -1
                  DrawingMode(#PB_2DDrawing_Gradient)
                  BackColor(\gradienthotbackcolor)
                  FrontColor(\gradienthotforecolor)
                  Select \gradienttype
                    Case #FlatButtonEx_Gradient_Boxed
                      BoxedGradient(0, 0, \w -1, \h -1)
                    Case #FlatButtonEx_Gradient_Custom
                      CustomGradient(\customcallback)
                    Default
                      LinearGradient(0, \h -1, \w -1, 0)
                  EndSelect
                  Box(2, 2, \w -3, \h -3)
                  DrawingMode(#PB_2DDrawing_Transparent)
                EndIf
                _FlatButtonExDraw_
               
              Case #PB_EventType_MouseLeave
                Box(0, 0, \w -1, \h -1, \backcolor)
                _FlatButtonExGradient_
                Line(0, 0, \w -1, 1, RGB(128, 128, 128))
                Line(0, \h -1, \w -1, 1, RGB(128, 128, 128))
                Line(0, 0, 1, \h -1, RGB(128, 128, 128))
                Line(\w -1, 0, 1, \h, RGB(128, 128, 128))
                _FlatButtonExDraw_
             
              Case #PB_EventType_LeftButtonDown
                _FlatButtonExDrawSunken_
            EndSelect
          EndIf
        StopDrawing()
      EndWith
    EndIf
  EndIf

EndProcedure

Procedure FlatButtonEx_Resize(*this.FlatButtonEx_ClassTemplate, x.i, y.i, w.i, h.i)
  If *this
    With *this
      If IsGadget(\ID)
        If x <> #PB_Ignore : \x = x : EndIf
        If y <> #PB_Ignore : \y = y : EndIf
        If w <> #PB_Ignore : \w = w : EndIf
        If h <> #PB_Ignore : \h = h : EndIf
        ResizeGadget(\ID, x, y, w, h)
        FlatButtonEx_Update(*this)
      EndIf
    EndWith
  EndIf
EndProcedure

Procedure FlatButtonEx_Disable(*this.FlatButtonEx_ClassTemplate, State.i = #True)
  If *this
    If IsGadget(*this\ID)
      *this\inactive = State
      FlatButtonEx_Update(*this)
      DisableGadget(*this\ID, State)
    EndIf
  EndIf
EndProcedure

Procedure FlatButtonEx_Hide(*this.FlatButtonEx_ClassTemplate, State.i = #True)
  If *this
    If IsGadget(*this\ID)
      HideGadget(*this\ID, State)
      FlatButtonEx_Update(*this)
    EndIf
  EndIf
EndProcedure

Procedure FlatButtonEx_Free(*this.FlatButtonEx_ClassTemplate)
  If *this
    With *this
      If IsGadget(\ID) : FreeGadget(\ID) : EndIf
      If IsImage(\sizedImage) : FreeImage(\sizedImage) : EndIf
      If \IsIco
        If IsImage(\Image) : FreeImage(\Image) : EndIf
      EndIf
    EndWith
    FreeMemory(*this)
    *this = 0
  EndIf
EndProcedure

DataSection
  vTable_FlatButtonEx:
  ; Getter Methodes
  Data.i @FlatButtonEx_GetID()
  Data.i @FlatButtonEx_GetX()
  Data.i @FlatButtonEx_GetY()
  Data.i @FlatButtonEx_GetWidth()
  Data.i @FlatButtonEx_GetHeight()
  Data.i @FlatButtonEx_GetData()
  Data.i @FlatButtonEx_GetColor()
  Data.i @FlatButtonEx_GetText()
  Data.i @FlatButtonEx_GetImage()
  Data.i @FlatButtonEx_GetSizedImage()
  Data.i @FlatButtonEx_GetShortCut()
  Data.i @FlatButtonEx_GetCursor()
 
  ; Setter Methodes
  Data.i @FlatButtonEx_SetFont()
  Data.i @FlatButtonEx_SetColor()
  Data.i @FlatButtonEx_SetText()
  Data.i @FlatButtonEx_SetImage()
  Data.i @FlatButtonEx_SetData()
  Data.i @FlatButtonEx_SetToolTip()
  Data.i @FlatButtonEx_SetShortCut()
  Data.i @FlatButtonEx_SetCursor()
  Data.i @FlatButtonEx_SetCustomCursor()
  Data.i @FlatButtonEx_SetGradient()
  Data.i @FlatButtonEx_SetHotGradient()
  Data.i @FlatButtonEx_SetGradientType()
 
  ; Other Methodes
  Data.i @FlatButtonEx_Update()
  Data.i @FlatButtonEx_Resize()
  Data.i @FlatButtonEx_Disable()
  Data.i @FlatButtonEx_Hide()
  Data.i @FlatButtonEx_Free()
EndDataSection
Have Fun

/ edit
Updated, fixed a memoryleak with images.

Re: FlatButtonEx Crossplattform

Posted: Fri Feb 22, 2013 4:16 pm
by ts-soft
Example:

Code: Select all

EnableExplicit

UsePNGImageDecoder()

XIncludeFile "FlatButtonEx.pbi"

#win_Main = 0
#Font1 = 0
#Font2 = 1

Enumeration ; Image
  #IMG_PureBasic
  #IMG_About
  #IMG_Exit
EndEnumeration

Procedure.f GradientCallback(x, y)
  ProcedureReturn Sin(x * 0.5) * Sin(y * 0.5)
EndProcedure

; On Linux or MacOS, please change the path to another picture to work!
LoadImage(#IMG_PureBasic, #PB_Compiler_Home + "Examples/Sources/Data/PureBasicLogo.bmp")
;
CatchImage(#IMG_About, ?Information_png_start)
CatchImage(#IMG_Exit, ?ExitSign_png_start)

LoadFont(#Font1, "Arial", 10)
LoadFont(#Font2, "Arial", 9, #PB_Font_Bold)

Define.FlatButtonEx btnLogo, btnAbout, btnText, btnExit

OpenWindow(#win_Main, #PB_Ignore, #PB_Ignore, 340, 120, "FlatButtonEx Example", #PB_Window_SystemMenu | #PB_Window_SizeGadget)
SmartWindowRefresh(#win_Main, #True)

btnLogo = New_FlatButtonEx(10, 10, WindowWidth(#win_Main) - 20, WindowHeight(#win_Main) - 50, #False, 0)
btnLogo\SetImage(#IMG_PureBasic)
btnLogo\SetToolTip("PureBasic Home")
btnLogo\SetCursor(#PB_Cursor_Hand)

btnAbout = New_FlatButtonEx(10, WindowHeight(#win_Main) - 30, 80, 25, #True, #PB_Shortcut_Return)
btnAbout\SetImage(#IMG_About)
btnAbout\SetText("About")
btnAbout\SetFont(#Font1)

btnText = New_FlatButtonEx(100, WindowHeight(#win_Main) - 30, WindowWidth(#win_Main) - 200, 25, #True, #PB_Shortcut_Return)
btnText\SetFont(#Font2)
btnText\SetText("Text only Button")
btnText\SetColor(#FlatButtonEx_Color_TextColor, $D9D9D9)
btnText\SetColor(#FlatButtonEx_Color_TextHotColor, $FFFFFF)
btnText\SetGradient($8A0000, $FF0303)
btnText\SetHotGradient($B90000, $FF3B3B)
btnText\SetGradientType(#FlatButtonEx_Gradient_Custom, @GradientCallback())

btnExit = New_FlatButtonEx(WindowWidth(#win_Main) - 90, WindowHeight(#win_Main) - 30, 80, 25, #True, #PB_Shortcut_Return)
btnExit\SetText("Exit")
btnExit\SetImage(#IMG_Exit)
btnExit\SetFont(#Font1)

SetActiveGadget(btnAbout\GetID())

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
    
    Case #PB_Event_SizeWindow
      btnLogo\Resize(#PB_Ignore, #PB_Ignore, WindowWidth(#win_Main) - 20, WindowHeight(#win_Main) - 50)
      btnAbout\Resize(#PB_Ignore, WindowHeight(#win_Main) - 30, #PB_Ignore, #PB_Ignore)
      btnText\Resize(#PB_Ignore, WindowHeight(#win_Main) - 30, WindowWidth(#win_Main) - 200, #PB_Ignore)
      btnExit\Resize(WindowWidth(#win_Main) - 90, WindowHeight(#win_Main) - 30, #PB_Ignore, #PB_Ignore)
      
    Case #PB_Event_Gadget
      Select EventGadget()
        Case btnLogo\GetID()
          If EventType() = #PB_EventType_LeftClick
            RunProgram("http:/www.purebasic.com")
          Else
            btnLogo\Update(EventType())
          EndIf

        Case btnAbout\GetID()
          If EventType() = #PB_EventType_LeftClick
            MessageRequester("FlatButtonEx", "Example by ts-soft")
          Else
            btnAbout\Update(EventType())
          EndIf
          
        Case btnText\GetID()
          If EventType() = #PB_EventType_LeftClick
            Debug "Text only Button clicked"
          Else
            btnText\Update(EventType())
          EndIf        

        Case btnExit\GetID()
          If EventType() = #PB_EventType_LeftClick
            Select MessageRequester("FlatButtonEx", "Are your sure?", #PB_MessageRequester_YesNo)
              Case #PB_MessageRequester_Yes
                Break
            EndSelect
          Else
            btnExit\Update(EventType())
          EndIf 
      EndSelect
  EndSelect
ForEver

DataSection
  Information_png_start:
    ; size : 484 bytes
    Data.q $0A1A0A0D474E5089,$524448490D000000,$1000000010000000,$FFF31F0000000608,$414449AB01000061
    Data.q $024BCF939DDA7854,$2FDB2CABBFC71051,$5D904410EB2484D7,$5D16105104450EC2,$241427F5BA5C820A
    Data.q $AE8763C13753A5D4,$4E8240FD26E952DD,$4125D514BA325D46,$9B5D5B6176B448B3,$CCC303A85929AE57
    Data.q $871E76666F3E663E,$9220D40E02040932,$914E262B9F0D2524,$4BB24005AB9D2559,$B972380195D027EA
    Data.q $5F4CD9B01DBB19F8,$A43217023CC9B711,$74CCA5CC3BF45691,$BB698B1033F3C75A,$6EDC27658AE65804
    Data.q $B386F077C4CC94BE,$DBA6563C9D261CFB,$6E6344489067AE2A,$A7411508F1E00957,$D43F30573BD81F37
    Data.q $A0C10F57E141D98C,$56BC38E8AD2037FA,$60A2014E1303C2D1,$63AB29E0075CD982,$B2CEC551EC4144FB
    Data.q $5ABBC157D7C88708,$F05921BD5555E240,$5F1E000D1D384479,$82DA34B16508D873,$1580CFE29D0101A9
    Data.q $AA7B14D8D61C316A,$E1E0CFDCD80605FE,$160B5B19934B0F25,$71D193210CFC76F4,$707B1A75C965AC7C
    Data.q $D166D2B567D07B47,$094A15AC8051F289,$3C406FF6DD0E36B6,$1ED20B5468D97FAE,$70E93ACC91600648
    Data.q $B776E3396593B5B5,$A5AF32F2E0162D5B,$C43F28D78E827A52,$DCD9C616F3FE0795,$52F6FB337678C6C6
    Data.q $9562946A1C399FB2,$872805D7951BE641,$9FCE7F2CDA300C34,$F9A81272ABBFF53B,$444E454900000000
    Data.b $AE,$42,$60,$82
  Information_png_end:

  ExitSign_png_start:
    ; size : 367 bytes
    Data.q $0A1A0A0D474E5089,$524448490D000000,$1000000010000000,$FFF31F0000000608,$4144493601000061
    Data.q $3010A06463DA7854,$00F10E874380C552,$B3B3B27EF5123E29,$84E4076CD408C2FB,$34A603205580E991
    Data.q $E18E70C73ECA6F7D,$AA9431A529E6101D,$E930C499DF7431E4,$31F07EF8BAAC2CDE,$4D76717431687168
    Data.q $88DB203DF0101B05,$5C026DDF392C08C1,$92FA8D143F2EFDA1,$5DEC213B74930C9A,$B00C4037381B0C76
    Data.q $9609C0C9CD976EFB,$A4A04170C58A5548,$CC34C15BE7FAC337,$0F38870C3A5DD900,$2290018496400C21
    Data.q $E3E06C0576EC7810,$C359AAD01B714FEF,$44EBD8AC05BD7D50,$204D60558B36C318,$7C193B9796C0C0D7
    Data.q $CCE817E80D31DDC4,$11CDFFB4D20C9986,$7689B3B0456E1506,$08D9388AE4104801,$94095E283A6DD906
    Data.q $AB1A60ADE3C18605,$031DE7F77858A001,$641857816DA04FC3,$1BC54837001AA3D7,$76965EFB2CCC2C6B
    Data.q $8403101D3816E18B,$B280E961080D5080,$DA640BCA29220894,$4DC3AE587F00070C,$490000000017426F
    Data.b $45,$4E,$44,$AE,$42,$60,$82
  ExitSign_png_end:
EndDataSection
Screenshot:
Image

Re: FlatButtonEx Crossplattform

Posted: Fri Feb 22, 2013 7:40 pm
by eJan
Thanks ts-soft, great work. Can i suggest small improvement: when clicked button and released outside >it receive event<, this should be the button restores to neutral when hoovering outside and back to clicked (if mouse click still pressed).

Re: FlatButtonEx Crossplattform

Posted: Fri Feb 22, 2013 8:15 pm
by ts-soft
If I have properly understood you, does require this that I determine the Mauspostition,
this required, which I know the ID of the window, around WindowMouse?() to be use.

But you can detect this in your main programm and use object\Update() to update the state!

Re: FlatButtonEx Crossplattform

Posted: Fri Feb 22, 2013 11:26 pm
by rsts
Thanks ts-soft. Another fine contribution.

cheers

Re: FlatButtonEx Crossplattform

Posted: Fri Feb 22, 2013 11:41 pm
by idle
works well thanks

Re: FlatButtonEx Crossplattform

Posted: Fri Feb 22, 2013 11:56 pm
by ts-soft
:D thx, is my first attempt with the CanvasGadget, I am no sign artist.

Re: FlatButtonEx Crossplattform

Posted: Sat Feb 23, 2013 12:53 am
by netmaestro
When you press a button, keep it pressed and drag the mouse off the button, the button should return to the unpressed state and when you release the mousebutton elsewhere, no button press event should fire. Your button isn't compliant with this standard behavior, it is firing the event. Aside from this, very good work! Thanks for sharing.

Re: FlatButtonEx Crossplattform

Posted: Sat Feb 23, 2013 1:42 am
by ts-soft
Thx for bugreport.

I hope it is fixed for windows. Linux fires the click before the buttondown :?

Re: FlatButtonEx Crossplattform

Posted: Sat Feb 23, 2013 7:19 pm
by ts-soft
Update:
History wrote:; Version 1.3 (Feb 23, 2013)
; added support for focusrectangle
; added support for spacebar to click
; changed Example to reflect the new features
History wrote:; Version 1.4 (Feb 23, 2013)
; fixed a bug with SupportKeyboard flag
; optimized the code
I miss some reports from MacUser, i have no Mac to test :cry:

Re: FlatButtonEx Crossplattform

Posted: Sat Feb 23, 2013 11:28 pm
by Andre
It runs very well on MacOS (10.5.8 here). Thanks a lot for sharing! :D

Re: FlatButtonEx Crossplattform

Posted: Sat Feb 23, 2013 11:42 pm
by ts-soft
Thx Andrè, that is great :D

Re: FlatButtonEx Crossplattform

Posted: Sun Feb 24, 2013 2:14 am
by ts-soft
Update:
History wrote:; Version 1.5 (Feb 24, 2013)
; added GetSpaceSupport() and SetSpaceSupport() methodes, to set or get this on runtime
; added GetCursor(), SetCursor() and SetCustomCursor methodes
; some Setter methodes return #TRUE on access
; some codeoptimation and bughunting

Re: FlatButtonEx Crossplattform

Posted: Sun Feb 24, 2013 7:46 am
by uwekel
Thank you very much, ts-soft!

On Linux, the used colors are hard-coded and disrespects system settings. I know it is hard to do and i have the same problem with own gadgets. What i want to say is that we urgently need some cross-platform functions to easily get the correct system colors, embedded into PureBasic core language.

Uwe

Re: FlatButtonEx Crossplattform

Posted: Sun Feb 24, 2013 10:01 am
by ts-soft
Yes, i have test some code for systemcolors from the forum, but nothing works :cry: