Ich bin einen anderen Weg zu einem Zeiteingabe-Gadget gegangen. Ich habe verstanden, dass Charly ein Windows-ähnliches Zeiteingabe-Gadget ("TimePicker") gesucht hat, und er hat ja auch bereits sein eindrucksvolles '3½-Tonner-SUV zum-Brötchen-holen'-Modell für Linux vorgestellt. Allerdings finde ich den Windows TimePicker für Linux- und Mac-Anwender, die nicht von Windows kommen, nicht besonders intuitiv. Und für Multiplattform-Programmierung bin ich eher für das KISS-Prinzip (
Keep
It
Simple
Stupid) und habe mich daher bewusst für die von Charly eigentliche verworfene Verwendung von SpinButtons entschieden, nachdem ich diesen Zeit- und Datums-Einstellungsdialog von Gnome gesehen habe:
Dies ist mit dem von PureBasic angebotenen und auf einem speziell modifizierten GTKBox-Gadget (mit jeweils einer GTKEventBox und GTKArrow für die Schaltflächen nach oben und nach unten) beruhenden SpinGadget nicht möglich. Daher war mein erster Versuch die Verwendung des GTK-Gadgets GtkSpinButton:
Code: Alles auswählen
EnableExplicit
ImportC ""
gtk_entry_set_text(*Entry.GtkEntry, Text.P-UTF8)
gtk_orientable_set_orientation(*Orientable, Orientation.I)
gtk_spin_button_new_with_range(Minimum.D, Maximum.D, StepIncrement.D)
EndImport
Define Layout.I
Define SpinButtonHour.I
Define SpinButtonMinute.I
Define TimeInfo.S
ProcedureC OutputCallback(*SpinButton.GtkSpinButton, UserData.I)
Static LastValue.I
Shared SpinButtonHour.I
Shared TimeInfo.S
Protected TimePart.S
Protected Value.I
Value = gtk_spin_button_get_value_as_int_(*SpinButton)
If Value <> LastValue Or LastValue = 0
TimePart = RSet(Str(Value), 2, "0")
gtk_entry_set_text(*SpinButton\entry, TimePart)
If *SpinButton = SpinButtonHour
TimeInfo = TimePart + ":" + Right(TimeInfo, 2)
Else
TimeInfo = Left(TimeInfo, 3) + TimePart
EndIf
StatusBarText(0, 0, TimeInfo, #PB_StatusBar_Center)
EndIf
LastValue = Value
ProcedureReturn #True
EndProcedure
TimeInfo = "00:00"
OpenWindow(0, 200, 100, 150, 120, "Time picker")
CreateStatusBar(0, WindowID(0))
AddStatusBarField(#PB_Ignore)
StatusBarText(0, 0, TimeInfo, #PB_StatusBar_Center)
Layout = g_list_nth_data_(gtk_container_get_children_(gtk_bin_get_child_(0 +
WindowID(0))), 0)
SpinButtonHour = gtk_spin_button_new_with_range(0, 23, 1)
gtk_orientable_set_orientation(SpinButtonHour, #GTK_ORIENTATION_VERTICAL)
gtk_spin_button_set_wrap_(SpinButtonHour, #True)
gtk_layout_put_(Layout, SpinButtonHour, 30, 15)
g_signal_connect_(SpinButtonHour, "output", @OutputCallback(), 0)
OutputCallback(SpinButtonHour, 0)
SpinButtonMinute = gtk_spin_button_new_with_range(0, 59, 1)
gtk_orientable_set_orientation(SpinButtonMinute, #GTK_ORIENTATION_VERTICAL)
gtk_spin_button_set_wrap_(SpinButtonMinute, #True)
gtk_layout_put_(Layout, SpinButtonMinute, 81, 15)
g_signal_connect_(SpinButtonMinute, "output", @OutputCallback(), 0)
OutputCallback(SpinButtonMinute, 0)
LoadFont(0, "CourierNew", 14, #PB_Font_Bold)
TextGadget(0, 70, 39, 10, 20, ":")
SetGadgetFont(0, FontID(0))
gtk_widget_show_all_(WindowID(0))
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Break
Case #PB_Event_Gadget
EndSelect
ForEver
Das sieht dann schon so ähnlich aus wie die Zeiteingabe im obigen Gnome-Dialog. Aber durch die verwendeten API-Befehle ist es ungünstig für die Verwendung in Multiplattform-geeigneten Programmen. Dann bin ich auf die Idee gekommen, statt SpinGadgets einfach ButtonGadgets zu verwenden. Und herausgekommen ist ein Ergebnis, das auf Linux, MacOS und Windows ziemlich ähnlich aussieht und sehr einfach aufgebaut ist. Der einzige verwendete API-Befehl zwingt MacOS dazu, die ButtonGadgets nicht standardmäßig mit abgerundeten Ecken anzuzeigen, sondern mit eckigen, sodass ein einheitliches Erscheinungsbild auf allen drei Plattformen gewährleistet ist. Erfolgreich getestet habe ich das letzte Beispiel auf diesen Betriebssystemen:
- Linux Mint 18.3 x64 Cinnamon mit PB 5.62 x64
- MacOS 10.6.8 (Snow Leopard) mit PB 5.62 x86
- Windows XP SP3 mit PB 5.62 x86
- Windows 7 SP1 x64 mit PB 5.62 x86
- Windows 10 x64 mit PB 5.62 x86
Linux Mint 18.3 mit Cinnamon:
MacOS 10.6.8:
Windows 7:
Code: Alles auswählen
EnableExplicit
#xOffset = 80
Structure IDEntries
IDButtonDown.I
IDButtonUp.I
IDText.I
MaxValue.I
EndStructure
Define Position.I
Define SelectedGadget.I
Define Text.S
Define TimeInfo.S
Define UpDownDetected.I
Define Value.I
NewList TimePicker.IDEntries()
Procedure CreateTimePicker(List TimePicker.IDEntries(), x.I, y.I,
DisplaySeconds.I = #False)
Protected FontButton.I
Protected FontName.S
Protected FontSizeButton.I
Protected FontSizeText.I
Protected FontText.I
Protected IDDelimiter.I
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Linux
FontName = "Courier"
FontSizeButton = 12
FontSizeText = 30
CompilerCase #PB_OS_MacOS
FontName = "Courier"
FontSizeButton = 22
FontSizeText = 34
CompilerCase #PB_OS_Windows
FontName = "Courier New"
FontSizeButton = 12
FontSizeText = 30
CompilerEndSelect
FontButton = LoadFont(#PB_Any, FontName, FontSizeButton, #PB_Font_Bold)
FontText = LoadFont(#PB_Any, FontName, FontSizeText, #PB_Font_Bold)
AddElement(TimePicker())
TimePicker()\MaxValue = 23
TimePicker()\IDButtonUp = ButtonGadget(#PB_Any, x, y, 66, 28, "+")
SetGadgetFont(TimePicker()\IDButtonUp, FontID(FontButton))
TimePicker()\IDText = TextGadget(#PB_Any, x, y + 28, 66, 44, "00",
#PB_Text_Border | #PB_Text_Center)
SetGadgetFont(TimePicker()\IDText, FontID(FontText))
TimePicker()\IDButtonDown = ButtonGadget(#PB_Any, x, y + 70, 66, 28, "-")
SetGadgetFont(TimePicker()\IDButtonDown, FontID(FontButton))
AddElement(TimePicker())
TimePicker()\MaxValue = 59
TimePicker()\IDButtonUp = ButtonGadget(#PB_Any, x + #xOffset, y, 66, 28, "+")
SetGadgetFont(TimePicker()\IDButtonUp, FontID(FontButton))
TimePicker()\IDText = TextGadget(#PB_Any, x + #xOffset, y + 28, 66, 44, "00",
#PB_Text_Border | #PB_Text_Center)
SetGadgetFont(TimePicker()\IDText, FontID(FontText))
TimePicker()\IDButtonDown = ButtonGadget(#PB_Any, x + #xOffset, y + 70, 66,
28, "-")
SetGadgetFont(TimePicker()\IDButtonDown, FontID(FontButton))
IDDelimiter = TextGadget(#PB_Any, x + #xOffset - 19, y + 27, 17, 35, ":")
SetGadgetFont(IDDelimiter, FontID(FontText))
If DisplaySeconds
AddElement(TimePicker())
TimePicker()\MaxValue = 59
TimePicker()\IDButtonUp = ButtonGadget(#PB_Any, x + #xOffset * 2, y, 66,
28, "+")
SetGadgetFont(TimePicker()\IDButtonUp, FontID(FontButton))
TimePicker()\IDText = TextGadget(#PB_Any, x + #xOffset * 2, y + 28, 66, 44,
"00", #PB_Text_Border | #PB_Text_Center)
SetGadgetFont(TimePicker()\IDText, FontID(FontText))
TimePicker()\IDButtonDown = ButtonGadget(#PB_Any, x + #xOffset * 2, y + 70, 66,
28, "-")
SetGadgetFont(TimePicker()\IDButtonDown, FontID(FontButton))
IDDelimiter = TextGadget(#PB_Any, x + #xOffset * 2 - 19, y + 27, 17, 35,
":")
SetGadgetFont(IDDelimiter, FontID(FontText))
EndIf
CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
ForEach TimePicker()
CocoaMessage(0, GadgetID(TimePicker()\IDButtonDown),
"setBezelStyle:", 10)
CocoaMessage(0, GadgetID(TimePicker()\IDButtonUp),
"setBezelStyle:", 10)
Next
CompilerEndIf
EndProcedure
OpenWindow(0, 270, 100, 270, 150, "Time picker")
CreateStatusBar(0, WindowID(0))
AddStatusBarField(#PB_Ignore)
CreateTimePicker(TimePicker(), 20, 20, #True)
TimeInfo = "00:00"
If ListSize(TimePicker()) = 3
TimeInfo + ":00"
EndIf
StatusBarText(0, 0, TimeInfo, #PB_StatusBar_Center)
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Break
Case #PB_Event_Gadget
SelectedGadget = EventGadget()
ForEach TimePicker()
Select SelectedGadget
Case TimePicker()\IDButtonDown
Value = Val(GetGadgetText(TimePicker()\IDText))
Value - 1
If Value = -1
Value = TimePicker()\MaxValue
EndIf
UpDownDetected = #True
Break
Case TimePicker()\IDButtonUp
Value = Val(GetGadgetText(TimePicker()\IDText))
Value + 1
If Value > TimePicker()\MaxValue
Value = 0
EndIf
UpDownDetected = #True
Break
EndSelect
Next
If UpDownDetected
Text = RSet(Str(Value), 2, "0")
SetGadgetText(TimePicker()\IDText, Text)
Position = (ListIndex(TimePicker()) + 1) * 3 - 2
TimeInfo = Left(TimeInfo, Position - 1) + Text +
Mid(TimeInfo, Position + 2)
StatusBarText(0, 0, TimeInfo, #PB_StatusBar_Center)
UpDownDetected = #False
EndIf
EndSelect
ForEver