Soucis de layout avec un NSColorPicker maison et comment faire le layout complètement à la main ?

Après avoir travaillé un temps considérable sur un panel additionnel pour le color picker macOS je l'ai finalement ajouté au-dit color picker pour tester et ça s'est pas super bien passé. Comme c'est une plaie à tester directement dans le color picker j'ai fait une app de test. Elle fonctionne comme il faut et qui surtout ne montre aucun signe de problème avec le layout :

C'est une fois que je l'ajoute au color picker que les ennuis commencent. Le layout se fait correctement mais le live resize est une catastrophe. Le contenu de la vue sautille ou est incohérent puis se stabilise. Aussi le layout peut casser suite à un live resize. Le même layout qui fonctionne très bien dans l'app de test (d'où l'idée que c'est autolayout qui est en faute).

Après moult pérégrinations j'en suis arrivé à dépouiller complètement le contenu du panel pour ne finir qu'avec un label dans une NSView sans aucune autre contrainte que l'auto-resizing mask. Le tout depuis un XIB et le résultat est pas top:

Trois petites précisions :

  • Le contenu du panel est wrappé dans une NSRemoteView comme pour les NSOpenPanel et NSSavePanel. Sécurité, sandbox, toussa....
  • Il est impossible de débugger le contenu de la vue avec le view debugger, je peux juste logger des messages et des descriptions d'objets dans Console.app via un Logger.
  • En donnant un fond de couleur à la vue qui englobe le contenu du panel on se rend compte que c'est elle qui sautille, comme si elle était mal accrochée en haut (mais pas en bas) de la fenêtre. Je ne sais pas si c'est bien clair sur le gif mais il ne semble pas y avoir de sautillement sur l'axe X. Si j'attache le label en bas de la vue, ça va (mais non, on n'aligne pas les choses vers le bas...).

En terme de hierarchie à la place du contenu du panel on a un NSLegacyExternalColorPickerHostViewController qui présente une NSRemoteView. Le reste est encore opaque et j'ai cherché dans toutes les bonnes crèmeries mais il n'y a rien sur le sujet.

Bref je suis vraiment coincé ici alors je suis preneur d'idées. Je vois différentes solutions :

  • NSRemoteView semble fonctionner via XPC ce qui induit un délais. En fait on dirait que la vue est en avance sur sa taille et non le contraire. Ou il y a un bug lié directement au système (dès que j'ai l'occasion, je teste sous macOS 13). Dans les deux cas je l'ai dans l'os. Under the hood la vue est ajoutée à une NSServiceViewControllerWindow qui semble ensuite 'marshallée' et envoyée au NSColorPanel
  • Le souci est lié directement à auto-layout et je dois alors m'en débarrasser. Mais comment faire, en 2022, sous macOS 12 se débarrasser d'autolayout ? Est-ce seulement possible ? Est-ce que je vais me souvenir comment on calcule des frames ?

Réponses

  • devulderdevulder Membre
    juin 2022 modifié #2

    var vx: NSRemoteView!

    Tu peux désactiver l'auto layout

    for constraint in vx.constraints
    {
       constraint.isActive = false
    }
    

    Sinon méthode old school, tu repositionne manuellement tes contrôles

    @objc func ChgSize()
    {
    }
    
    vx.postsFrameChangedNotifications = true
    
    NotificationCenter.default.addObserver(self, selector:#selector(ChgSize), name: NSView.frameDidChangeNotification, object: vx)
    

    A voir....

  • PyrohPyroh Membre

    J'ai fouillé partout et ou constraints est vide ou c'est des contraintes que j'ai créé moi (pour tester).
    Bref en ajoutant des vues un peu plus complexes que des labels on peut récupérer des erreurs dans la console du genre :

    Unable to simultaneously satisfy constraints:
    (
        "<NSAutoresizingMaskLayoutConstraint:0x6000000b0b40 h=-&- v=-&- NSView:0x123706c80.minY == 0   (active, names: '|':NSNextStepFrameViewBridge:0x113605810 )>",
        "<NSAutoresizingMaskLayoutConstraint:0x6000000b1ea0 h=-&- v=-&- V:|-(0)-[NSView:0x123706c80]   (active, names: '|':NSNextStepFrameViewBridge:0x113605810 )>",
        "<NSLayoutConstraint:0x6000000a43c0 'NSWindow-current-height' NSNextStepFrameViewBridge:0x113605810.height == 0   (active)>",
        "<NSAutoresizingMaskLayoutConstraint:0x6000000a5720 h=-&- v=-&- NSStackView:0x12485e7c0.minY == 0   (active, names: '|':Content view:0x123752370 )>",
        "<NSAutoresizingMaskLayoutConstraint:0x6000000a5770 h=-&- v=-&- V:|-(0)-[NSStackView:0x12485e7c0]   (active, names: Content view:0x123752370, '|':Content view:0x123752370 )>",
        "<NSLayoutConstraint:0x6000000a5860 'NSStackView.Edge.Top' V:|-(>=0)-[FireworksContent.FireworksColorWell:0x12488f410]   (active, names: '|':NSStackView:0x12485e7c0 )>",
        "<NSLayoutConstraint:0x6000000a5a90 'NSStackView.Edge.Bottom' V:[FireworksContent.FireworksColorWell:0x12488f410]-(>=8)-|   (active, names: '|':NSStackView:0x12485e7c0 )>",
        "<NSAutoresizingMaskLayoutConstraint:0x6000000a5c20 h=-&- v=-&- Content view.minY == 0   (active, names: Content view:0x123752370, '|':NSView:0x123706c80 )>",
        "<NSAutoresizingMaskLayoutConstraint:0x6000000a5c70 h=-&- v=-&- V:|-(0)-[Content view]   (active, names: Content view:0x123752370, '|':NSView:0x123706c80 )>"
    )
    
    Will attempt to recover by breaking constraint 
    <NSLayoutConstraint:0x6000000a5a90 'NSStackView.Edge.Bottom' V:[FireworksContent.FireworksColorWell:0x12488f410]-(>=8)-|   (active, names: '|':NSStackView:0x12485e7c0 )>
    
    Set the NSUserDefault NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints to YES to have -[NSWindow visualizeConstraints:] automatically called when this happens.  And/or, set a symbolic breakpoint on LAYOUT_CONSTRAINTS_NOT_SATISFIABLE to catch this in the debugger.
    

    C'est des layouts qui fonctionnent au poil dans une NSWindow standard. Bref c'est plein de bugs je vais trouver une autre solution et abandonner le color picker.
    Y'a des jours où ce métier me fatigue...

  • ca a pas l'air violent de mettre cela sans auto layout
    px tu m'envoyer ton xib ?

  • PyrohPyroh Membre

    Alors je peux pas t'envoyer le XIB en question pour des raison de confidentialité des sources.
    Mais j'ai refait un petit projet vite-fait avec un color picker custom. C'est très simple et tu vas pouvoir contempler l'ampleur des dégâts. Le tout est dans le zip attaché.

  • @Pyroh a dit :
    Alors je peux pas t'envoyer le XIB en question pour des raison de confidentialité des sources.
    Mais j'ai refait un petit projet vite-fait avec un color picker custom. C'est très simple et tu vas pouvoir contempler l'ampleur des dégâts. Le tout est dans le zip attaché.

    cool, je regarde cela ce week!

  • Hello,
    J'ai essayer en mettant des contrôles dans une vue en code, un chouilla moins pire :)
    Mais bon c'est pas le top

  • PyrohPyroh Membre

    Ouais c'est les mêmes soucis que j'ai pu avoir durant mes tests. C'est pas fiable leur NSRemoteView. Je sais pas si je vais prendre le temps de faire un radar, je suis occupé à ré-implémenter des morceaux du color picker.

    En tout cas merci d'avoir pris le temps d'essayer 😃

Connectez-vous ou Inscrivez-vous pour répondre.