Wie kann man ein Custom NSPopUpButton erstellen?

MAC OSX spezifisches Forum
Beiträge, die plattformübergreifend sind, gehören ins 'Allgemein'-Forum.
Wolfram
Beiträge: 28
Registriert: 23.08.2013 14:38
Computerausstattung: OSX 10.13 | PB 5.46

Wie kann man ein Custom NSPopUpButton erstellen?

Beitrag von Wolfram »

Hallo,

weiß jemand wie man wie man ein NSPopUpButton / ComboBoxGadget() anpasst?
Eigentlich hätte ich erwartet das es mit diesem Beispiel geht, da das NSPopUpButton auf einem Button basiert, aber leider geht es nicht.
viewtopic.php?p=350901#p350901
OSX 10.13 | PB 5.46
Benutzeravatar
Shardik
Beiträge: 738
Registriert: 25.01.2005 12:19

Re: Wie kann man ein Custom NSPopUpButton erstellen?

Beitrag von Shardik »

Was hast Du genau vor? Möchtest Du bei einem ButtonGadget die Text- und Hintergrundfarbe ändern? Dazu habe ich in meiner Trickkiste dieses Beispiel gefunden. Leider habe ich noch keine Möglichkeit gefunden, Text- und Hintergrundfarbe gleichzeitig zu ändern. Erfolgreich getestet habe ich das Beispiel auf MacOS 10.13.6 'High Sierra' mit PB 5.46 x64 im ASCII- und Unicode-Modus.

Code: Alles auswählen

EnableExplicit

Procedure SetGadgetColorEx(GadgetID.I, ColorType.I, Color.I)
  Protected Alpha.CGFloat
  Protected *AttributedTitle
  Protected Blue.CGFloat
  Protected CIColor.I
  Protected Filter.I
  Protected FilterArray.I
  Protected Green.CGFloat
  Protected NSColor.I
  Protected Range.NSRange
  Protected Red.CGFloat

  If GadgetType(GadgetID) = #PB_GadgetType_Button
    Alpha = 1.0
    Red = Red(Color) / 255
    Green = Green(Color) / 255
    Blue = Blue(Color) / 255

    Select ColorType
      Case #PB_Gadget_BackColor
        Filter = CocoaMessage(0, 0,
          "CIFilter filterWithName:$", @"CIFalseColor")
        CocoaMessage(0, Filter, "setDefaults")
        CIColor = CocoaMessage(0, 0, "CIColor colorWithRed:@", @Red,
          "green:@", @Green, "blue:@", @Blue)
        CocoaMessage(0, Filter,
          "setValue:", CIColor,
          "forKey:$", @"inputColor1")
        FilterArray = CocoaMessage(0, 0, "NSArray arrayWithObject:", Filter)
        CocoaMessage(0, GadgetID(GadgetID), "setWantsLayer:", #YES)
        CocoaMessage(0, GadgetID(GadgetID), "setContentFilters:", FilterArray)
      Case #PB_Gadget_FrontColor
        *AttributedTitle = CocoaMessage(0, CocoaMessage(0, 0,
          "NSMutableAttributedString alloc"), "initWithAttributedString:",
          CocoaMessage(0, GadgetID(GadgetID), "attributedTitle"))
        Range\length = CocoaMessage(0, *AttributedTitle, "length")
        NSColor = CocoaMessage(0, 0,
          "NSColor colorWithDeviceRed:@", @Red,
          "green:@", @Green,
          "blue:@", @Blue,
          "alpha:@", @Alpha)
        CocoaMessage(0, *AttributedTitle,
          "addAttribute:$", @"NSColor",
          "value:", NSColor,
          "range:@", @Range)
        CocoaMessage(0, GadgetID(GadgetID),
          "setAttributedTitle:", *AttributedTitle)
    EndSelect
  Else
    SetGadgetColor(GadgetID, ColorType, Color)
  EndIf
EndProcedure

Macro SetGadgetColor(GadgetID, ColorType, Color)
  SetGadgetColorEx(GadgetID, ColorType, Color)
EndMacro

OpenWindow(0, 270, 100, 230, 110, "Colored ButtonGadget")

ButtonGadget(0, 10, 20, WindowWidth(0) - 20, 30,
  "Button with yellow background")
SetGadgetColor(0, #PB_Gadget_BackColor, $00FFFF)

ButtonGadget(1, 10, 60, WindowWidth(0) - 20, 30,
  "Button with blue text")
SetGadgetColor(1, #PB_Gadget_FrontColor, $FF0000)

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Mit einer ähnlichen Vorgehensweise kann auch die Hintergrundfarbe eines nicht editierbaren ComboBoxGadget (NSPopUpButton) geändert werden (ebenfalls erfolgreich getestet auf MacOS 10.13.6 'High Sierra' mit PB 5.46 x64 im ASCII- und Unicode-Modus):

Code: Alles auswählen

EnableExplicit

Define i.I

Procedure SetComboBoxBackColor(GadgetID.I, Color.I)
  Protected Alpha.CGFloat
  Protected Blue.CGFloat
  Protected CIColor.I
  Protected Filter.I
  Protected FilterArray.I
  Protected Green.CGFloat
  Protected Red.CGFloat

  Alpha = 1.0
  Red = Red(Color) / 255
  Green = Green(Color) / 255
  Blue = Blue(Color) / 255

  Filter = CocoaMessage(0, 0,
    "CIFilter filterWithName:$", @"CIFalseColor")
  CocoaMessage(0, Filter, "setDefaults")
  CIColor = CocoaMessage(0, 0, "CIColor colorWithRed:@", @Red,
    "green:@", @Green, "blue:@", @Blue)
  CocoaMessage(0, Filter,
    "setValue:", CIColor,
    "forKey:$", @"inputColor1")
  FilterArray = CocoaMessage(0, 0, "NSArray arrayWithObject:", Filter)
  CocoaMessage(0, GadgetID(GadgetID), "setWantsLayer:", #YES)
  CocoaMessage(0, GadgetID(GadgetID), "setContentFilters:", FilterArray)
EndProcedure

OpenWindow(0, 100, 100, 200, 90, "Colored ComboBox")

ComboBoxGadget(0, 10, 20, WindowWidth(0) - 20, 25)
SetComboBoxBackColor(0, $00FFFF)

For i = 1 To 5
  AddGadgetItem(0, -1, "Item " + Str(i))
Next i

SetGadgetState(0, 0)

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Wolfram
Beiträge: 28
Registriert: 23.08.2013 14:38
Computerausstattung: OSX 10.13 | PB 5.46

Re: Wie kann man ein Custom NSPopUpButton erstellen?

Beitrag von Wolfram »

Hi Shardik,

ich würde gern ein eigenes image nutzen wie in diesem Beispiel.
viewtopic.php?p=350901#p350901

Das sollte doch gehen, da der NSPopUpButton doch auf einem NSButten beruht.
OSX 10.13 | PB 5.46
Benutzeravatar
Shardik
Beiträge: 738
Registriert: 25.01.2005 12:19

Re: Wie kann man ein Custom NSPopUpButton erstellen?

Beitrag von Shardik »

Bei einem nicht editierbaren ComboBoxGadget (NSPopUpButton) musst Du im Gegensatz zu meinem verlinkten ButtonGadget-Beispiel noch mit einem Callback wantsUpdateLayer abfangen und immer #YES zurückgeben, dann funktioniert es genauso wie beim ButtonGadget-Beispiel. Allerdings entsteht beim ComboBoxGadget dann das Problem, dass unter dem Grafik-Layer die Schaltfläche mit den Pfeilen nach oben und unten versteckt ist...

Code: Alles auswählen

EnableExplicit

UsePNGImageDecoder()

Define i.I
Define SubclassedComboBoxGadget.I

Procedure SubclassGadget(GadgetID.I, NewClassName.S)
  Protected GadgetClass.I = CocoaMessage(0, GadgetID(GadgetID), "class")
  Protected NewGadgetClass.I

  NewGadgetClass = objc_allocateClassPair_(GadgetClass, NewClassName, 0)
  objc_registerClassPair_(NewGadgetClass)
  object_setClass_(GadgetID(GadgetID), NewGadgetClass)

  ProcedureReturn NewGadgetClass
EndProcedure

ProcedureC UpdateLayer(SubclassedComboBox.I, Selector.I)
  Protected Cell.I
  Protected Layer.I
  Protected Rect.NSRect

  Cell = CocoaMessage(0, SubclassedComboBox, "cell")
  Layer = CocoaMessage(0, SubclassedComboBox, "layer")

  If CocoaMessage(0, Cell, "isHighlighted")
    CocoaMessage(0, Layer, "setContents:", ImageID(1))
  Else
    CocoaMessage(0, Layer, "setContents:", ImageID(0))
    CocoaMessage(@Rect, Layer, "contentsCenter")
    Rect\origin\x = 0.5
    Rect\origin\y = 0.5
    Rect\size\width = 0
    Rect\size\height = 0
    CocoaMessage(0, Layer, "setContentsCenter:@", @Rect)
  EndIf
EndProcedure

ProcedureC WantsUpdateLayer(SubclassedComboBox.I, Selector.I)
  ProcedureReturn #YES
EndProcedure

If LoadImage(0, "button.png") And LoadImage(1, "button_pressed.png")
  OpenWindow(0, 270, 100, 260, 90, "Subclassed ComboBoxGadget")
  ComboBoxGadget(0, 60, 30, 140, 20)

  For i = 1 To 5
    AddGadgetItem(0, -1, "Item " + Str(i))
  Next i

  SetGadgetState(0, 0)

  CocoaMessage(0, GadgetID(0), "setWantsLayer:", #YES)
  SubclassedComboBoxGadget = SubclassGadget(0, "SubclassedComboBoxGadget")
  class_addMethod_(SubclassedComboBoxGadget,
    sel_registerName_("updateLayer"), @UpdateLayer(), "v@")
  class_addMethod_(SubclassedComboBoxGadget,
    sel_registerName_("wantsUpdateLayer"), @WantsUpdateLayer(), "v@")
  
  Repeat
  Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Wolfram
Beiträge: 28
Registriert: 23.08.2013 14:38
Computerausstattung: OSX 10.13 | PB 5.46

Re: Wie kann man ein Custom NSPopUpButton erstellen?

Beitrag von Wolfram »

Strange. Bis auf das wantsUpdateLayer hatte ich das gemacht, aber der callback wurde nie aufgerufen.

Computer, manchmal möchten sie nur um den Block getragen werden. ;-)

Danke!
OSX 10.13 | PB 5.46
Benutzeravatar
Shardik
Beiträge: 738
Registriert: 25.01.2005 12:19

Re: Wie kann man ein Custom NSPopUpButton erstellen?

Beitrag von Shardik »

Wolfram hat geschrieben:Bis auf das wantsUpdateLayer hatte ich das gemacht, aber der callback wurde nie aufgerufen.
Immer wenn ein Callback nicht aufgerufen wird, liegt es meist daran, dass vorher ein anderer Callback aufgerufen werden muss. Um beim NSPopUpButton den Callback updateLayer auslösen zu lassen, ist der Callback wantsUpdateLayer zwingend erforderlich, da diese intern aufgerufene Methode ohne Callback standardmäßig #NO zurückgibt. Erst wenn stattdessen #YES im Callback wantsUpdateLayer zurückgegeben wird, wird auch updateLayer ausgelöst. Warum dies im NSButton-Beispiel nicht nötig ist, kann ich Dir leider auch nicht sagen.

Ich weiss nicht, ob Du auch den Dokumentations-Browser Dash einsetzt, aber dieser ist für 27,99 € eine unglaublich nützliche und hilfreiche Anschaffung. Danilo hatte ihn im englischen Forum hier empfohlen und auch gleich gezeigt, wie man Dash als Tool einrichtet, den Cursor auf z.B. NSPopUpButton setzt, und nach Drücken der Tastenkombination <Alt> + <F1> alle Methoden und Erklärungen zur gewünschten Klasse in Dash angezeigt bekommt.

Ich selbst habe bis vor kurzem das kostenlose Ingredients eingesetzt, das in Danilos Thread von Wilbert erwähnt und verlinkt ist. Allerdings läuft Ingredients nur auf Snow Leopard korrekt, und es ist seitdem von den Autoren leider nicht mehr an das ständig von Apple modifizierte DocSet-Format angepasst worden. Mit dem hier von aksvenk vorgeschlagenen Symlink lässt sich Ingredients noch bis Mavericks verwenden.
Wolfram
Beiträge: 28
Registriert: 23.08.2013 14:38
Computerausstattung: OSX 10.13 | PB 5.46

Re: Wie kann man ein Custom NSPopUpButton erstellen?

Beitrag von Wolfram »

Danke für den Tip. Dash benutze ich schon seit zwei Jahren, aber mit dem Helper von Danilo ist es noch mal ein Sprung nach vorne. :-)

Leider habe ich seit der Umstellung auf OSX 10.13, Xcode 8 das Problem das vieles Funktionen in Dash nicht gefunden werden.

Wenn ich zum Beispiel nach "setWantsLayer" such habe ich nur Google Treffer, nicht aber in der Apple API. Ich bekomme leider auch das alte Cocoa Docset von Xcode 4 nicht mehr installiert.
Da ging das noch.

Wenn Du keine Bessere Idee Hast werde ich mit Hilfe des des Helpers das "set" bei den Befehlen entfernen.


Edit: Da ist leider noch mehr der Wurm drin. Ich kann zum Beispiel auch nicht nach "CIFalseColor" such.
        Ich kann mich nicht daran erinnern das ich das Problem jemals aufweinen alten Rechner hatte. :-/
Zuletzt geändert von Wolfram am 09.02.2019 14:01, insgesamt 1-mal geändert.
OSX 10.13 | PB 5.46
Benutzeravatar
Shardik
Beiträge: 738
Registriert: 25.01.2005 12:19

Re: Wie kann man ein Custom NSPopUpButton erstellen?

Beitrag von Shardik »

Wolfram hat geschrieben:Leider habe ich seit der Umstellung OSX 10.13, Xcode 8 das Problem das vieles nicht gefunden wird.
Welche genaue Version von 10.13 setzt Du ein? Der letzte Point-Release ist 10.13.6. Du solltest zusehen, dass Du über Updates unbedingt auf diesen Versionsstand kommst, alleine schon um alle Sicherheitslücken und Fehler zu beheben. Und die Xcode-Version ist auch veraltet. Du solltest unbedingt entweder Xcode 9.4.1 installieren (die letzte Version für das SDK von 10.13) oder 10.1 (diese Version unterstützt schon das SDK von 10.14 und Du kannst sehen, welche neuen Methoden in Mojave hinzugekommen sind, eine 32-Bit Kompilierung ist dann aber nicht mehr möglich). Nach Installation der aktuellsten Xcode-Version 9.4.1 oder 10.1 solltest Du in den Einstellungen von Xcode das aktuelle DocSet herunterladen. Das sollte Dash dann erkennen.

Ein anderes Problem könnte in der Dash-Version liegen. Du solltest immer einen Update auf die aktuellste Version vornehmen, denn Dash wird ständig an Änderungen von Apples DocSet-Format angepasst. Eine ältere Dash-Version könnte also Probleme im Lesen und Darstellen des aktuellen DocSet-Formats haben.
Wolfram hat geschrieben:Ich bekomme leider auch das alte Cocoa Docset von Xcode 4 installiert.
Meinst Du, dass in Dash das alte DocSet von Xcode 4 auch angezeigt wird? Das kannst Du in den Einstellungen von Dash deaktivieren oder die Durchsuchungs-Reihenfolge ändern.
Wolfram
Beiträge: 28
Registriert: 23.08.2013 14:38
Computerausstattung: OSX 10.13 | PB 5.46

Re: Wie kann man ein Custom NSPopUpButton erstellen?

Beitrag von Wolfram »

Ich habe OSX 10.13.6.
Ich bin immer vorsichtig mit Neuerungen, da Apple sehr schnell alte Sachen wegfallen lässt.
Meinst Du, dass in Dash das alte DocSet von Xcode 4 auch angezeigt wird? Das kannst Du in den Einstellungen von Dash deaktivieren oder die Durchsuchungs-Reihenfolge ändern.
In meinem Satz fehlte das nicht. Ich meinte das ich das Dorset von Xcode 4 nicht mehr in das Dash installiert bekomme.


Sorry für die ganzen Tippfehler. Mit einer kaputten Tastatur und automatischer Schreibkorrektur führen die Texte ein Eigenleben. :-)

Kannst Du in Dash nach "CIFalseColor" suchen? Ich habe dazu in der Apple API kein Treffer obwohl es darin steht.
OSX 10.13 | PB 5.46
Antworten