Page 1 of 2

Check gadget enable/disable status

Posted: Wed Jul 31, 2013 10:37 am
by SkyManager
Hi,

We can use disableGadget() function to set the gadget enable/disable status

BUT

How can we check the gadget enable/disable status

something like,

getGadgetEnableStatus(#GadgetID)

Re: Check gadget enable/disable status

Posted: Wed Jul 31, 2013 10:50 am
by Shardik
Cross-platform API-solution for Linux, MacOS and Windows:

Code: Select all

Procedure IsGadgetDisabled(GadgetNumber)
  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Linux
      Protected *Widget.GtkWidget = GadgetID(GadgetNumber)
      ProcedureReturn Bool(*Widget\state)
    CompilerCase #PB_OS_MacOS
      ProcedureReturn CocoaMessage(0, GadgetID(GadgetNumber), "isEnabled") ! 1
    CompilerCase #PB_OS_Windows
      ProcedureReturn IsWindowEnabled_(GadgetID(GadgetNumber)) ! 1
  CompilerEndSelect
EndProcedure

OpenWindow(0, 0, 0, 250, 105, "Disable/enable buttons...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ButtonGadget(0, 10, 15, 230, 30, "Disabled Button") : DisableGadget(0, 1)
ButtonGadget(1, 10, 60, 230, 30, "Enabled Button") : DisableGadget(1, 0)

Debug IsGadgetDisabled(0)
Debug IsGadgetDisabled(1)

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Update: I extended the Windows API code with API code for Linux and MacOS to offer a true cross-platform solution without the disadvantages of the code examples of the following postings... :wink:

For those of you who don't need a cross-platform solution and don't want the additional source code lines for the other operating systems you only need to remove the unwanted source code lines. For Windows you simply change the procedure to

Code: Select all

Procedure IsGadgetDisabled(GadgetNumber)
  ProcedureReturn IsWindowEnabled_(GadgetID(GadgetNumber)) ! 1
EndProcedure

Re: Check gadget enable/disable status

Posted: Wed Jul 31, 2013 11:37 am
by RASHAD
Cross platform

Code: Select all

Procedure IsGadgetDisabled(GadgetNumber)
  SetActiveGadget(GadgetNumber)
  If GetActiveGadget() < 0
     Debug "Gadget "+Str(GadgetNumber)+" Disabled"
  Else
     Debug "Gadget "+Str(GadgetNumber)+" Enabled"
  EndIf
EndProcedure

OpenWindow(0, 0, 0, 250, 105, "Disable/enable buttons...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ButtonGadget(0, 10, 15, 230, 30, "Disabled Button") : DisableGadget(0, 1)
ButtonGadget(1, 10, 60, 230, 30, "Enabled Button") : DisableGadget(1, 0)

IsGadgetDisabled(0)
IsGadgetDisabled(1)



Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow


Re: Check gadget enable/disable status

Posted: Wed Jul 31, 2013 12:05 pm
by PB
> SetActiveGadget(GadgetNumber)

Eww, yuck! :) You shouldn't change the focus to test a state.
The gadget with the focus should stay that way at all times:

Code: Select all

Procedure IsGadgetDisabled(GadgetNumber)
  SetActiveGadget(GadgetNumber)
  If GetActiveGadget() < 0
     Debug "Gadget "+Str(GadgetNumber)+" Disabled"
  Else
     Debug "Gadget "+Str(GadgetNumber)+" Enabled"
  EndIf
EndProcedure

OpenWindow(0, 0, 0, 250, 150, "Disable/enable buttons...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ButtonGadget(0, 10, 15, 230, 30, "Disabled Button") : DisableGadget(0, 1)
ButtonGadget(1, 10, 60, 230, 30, "Enabled Button") : DisableGadget(1, 0)
StringGadget(2, 10, 110, 230, 30, "This is meant to have the focus!")
SetActiveGadget(2)

IsGadgetDisabled(0)
IsGadgetDisabled(1)

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow

Re: Check gadget enable/disable status

Posted: Wed Jul 31, 2013 12:17 pm
by TI-994A
SkyManager wrote:How can we check the gadget enable/disable status
something like getGadgetEnableStatus(#GadgetID)
Hi SkyManager. Here's a simple macro-based solution with no additional variables or arrays to maintain.

Code: Select all

Macro EnableGadget(gadgetNo)
  DisableGadget(gadgetNo, 0)
  SetGadgetData(gadgetNo, 0)
EndMacro

Macro DisableGadgetEx(gadgetNo)
  DisableGadget(gadgetNo, 1)
  SetGadgetData(gadgetNo, 1)
EndMacro

Procedure GadgetStatus(gadgetNo)
  ProcedureReturn -(GetGadgetData(gadgetNo) - 1)
EndProcedure

OpenWindow(0, 50, 50, 220, 75, "Gadget Enabled/Disabled")
ButtonGadget(0, 60, 15, 100, 20, "Click to toggle")
ButtonGadget(1, 60, 40, 100, 20, "TEST BUTTON")
DisableGadgetEx(1)

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      appQuit = 1
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 0
          If GadgetStatus(1)
            DisableGadgetEx(1)
          Else
            EnableGadget(1)
          EndIf
        Case 1
          DisableGadgetEx(1)
      EndSelect
  EndSelect
Until appQuit = 1
Simple and cross-platform. :)

Re: Check gadget enable/disable status

Posted: Wed Jul 31, 2013 12:45 pm
by RASHAD
OK PB how about that :)

Code: Select all

Procedure IsGadgetDisabled(GadgetNumber)
  Result = GetActiveGadget()
  If IsGadget(result) And Result <> GadgetNumber
     DisableGadget(Result,1)
  EndIf
  SetActiveGadget(GadgetNumber)
  If GetActiveGadget() < 0
     Debug "Gadget "+Str(GadgetNumber)+" Disabled"
  Else
     Debug "Gadget "+Str(GadgetNumber)+" Enabled"
  EndIf
  If IsGadget(result)
     DisableGadget(Result,0)
     SetActiveGadget(Result)
  EndIf
  
EndProcedure

OpenWindow(0, 0, 0, 250, 150, "Disable/enable buttons...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ButtonGadget(0, 10, 15, 230, 30, "Disabled Button") : DisableGadget(0, 1)
ButtonGadget(1, 10, 60, 230, 30, "Enabled Button") : DisableGadget(1, 0)
StringGadget(2, 10, 110, 230, 30, "This is meant to have the focus!")
SetActiveGadget(2)

IsGadgetDisabled(0)
IsGadgetDisabled(1)
Debug GetActiveGadget()

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow

Re: Check gadget enable/disable status

Posted: Wed Jul 31, 2013 2:01 pm
by BorisTheOld
@TI-994A -- This will only work if the gadget data is not already in use.

@RASHAD -- In an event driven system it's bad policy to change the program state in order to test the program state. All testing needs to be passive, otherwise the act of temporarily moving focus can cause big problems in the code.

In our own applications we assign a structure to each gadget to track it's status. The address of the structure is stored in the gadget data field. We do this because of the limitations in PB, such as the lack of many events and features that are standard in the native operating systems.

Each time we change the application state we modify the gadget status information. We also create custom events to simulate missing PB events, such as GotFocus and LostFocus for buttons.

Re: Check gadget enable/disable status

Posted: Wed Jul 31, 2013 2:12 pm
by RASHAD
Sorry BorisTheOld
I do not agree with you
Change the status of a an object (not the program) temporary then get the right status back at the same time will not cause any harm
sorry

Re: Check gadget enable/disable status

Posted: Wed Jul 31, 2013 2:55 pm
by BorisTheOld
RASHAD wrote:Change the status of a an object (not the program) temporary then get the right status back at the same time will not cause any harm
When you change the state of a gadget, you're changing the state of the program. Events will be created that can have unexpected consequences. As TI-994A said, it's a bad idea.

Re: Check gadget enable/disable status

Posted: Wed Jul 31, 2013 3:07 pm
by TI-994A
BorisTheOld wrote:@TI-994A -- This will only work if the gadget data is not already in use.
Of course, but the gadget data is perfect for these types of flags. After all, not much can be done with this single numeric field.
BorisTheOld wrote:As TI-994A said, it's a bad idea.
I believe that's a misquote. :lol:

However, both points have merit. On the one hand, it may be alright to programmatically change focus, if such a change is associated with some user-initiated event. But, on the other hand, it may not be a good idea to automate such changes, as it can interfere with normal input and work flow. IMHO.

Re: Check gadget enable/disable status

Posted: Wed Jul 31, 2013 3:09 pm
by RASHAD
I still do not agree with you
Shall we ask Fred to not support anymore HideGadget(),DisableGadget()
and MicroSoft as well ?
TI-994A did not say it's a bad idea
PB who said that

Re: Check gadget enable/disable status

Posted: Wed Jul 31, 2013 3:29 pm
by BorisTheOld
RASHAD wrote:Shall we ask Fred to not support anymore HideGadget(),DisableGadget()
and MicroSoft as well ?
That's a specious argument.

I'm saying that if you temporarily move focus from one gadget to another, then move focus back to the original, you will create a series of LostFocus/GotFocus events that might cause problems in the code. Depending on the program logic, fields may get re-initialized out of sequence, or data may be written to files. It's just not a good idea.
RASHAD wrote:TI-994A did not say it's a bad idea
PB who said that
I misspelt PB's name. :)

Re: Check gadget enable/disable status

Posted: Thu Aug 01, 2013 1:36 pm
by PB
> you will create a series of LostFocus/GotFocus events

+1. Of course, you can code around it (set a flag when
you're doing focus change) but why should we need to?
A cross-platform PureBasic command is needed for this.

Re: Check gadget enable/disable status

Posted: Fri Aug 02, 2013 3:43 pm
by JHPJHP
Not sure it makes a difference: PB 5.20 Beta 8 x86 (Windows 7 64bit)

Even though the documentation states there is no return value...
- and yes I realize that the state is being changed (but only half of the time) :)

*** I would use the Shardik solution posted above before my example ***

Code: Select all

Procedure.s IsGadgetEnabled(gNumber)
  Result.s = ""
  
  Select 8
    Case DisableGadget(gNumber, 0)
      DisableGadget(gNumber, 1)
      Result = "Disabled"
    Default
      Result = "Enabled"
  EndSelect
  ProcedureReturn Result
EndProcedure

If OpenWindow(0, 0, 0, 250, 105, "Disable/enable buttons...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ButtonGadget(0, 10, 15, 230, 30, "Disabled Button") : DisableGadget(0, 1)
  ButtonGadget(1, 10, 60, 230, 30, "Enabled Button") : DisableGadget(1, 0)
  Debug IsGadgetEnabled(0)
  Debug IsGadgetEnabled(1)
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf

Re: Check gadget enable/disable status

Posted: Sat Aug 03, 2013 3:31 am
by PB
> if you temporarily move focus from one gadget to another,
> then move focus back to the original

You will interrupt the user when they're typing or selecting text.