Comment gérer une vue personnalisée?

2»

Réponses

  • GreensourceGreensource Membre
    21:54 modifié #32
    Re-bonjour!
    Je me demandais comment modifier un Path avec une transformation CGAffineTransform?
    L'appliquer carrément au context je saurais le faire je pense (CGContextConcatCTM).
    Mais je ne trouve pas de fonction équivalente pour modifié mon CGPathRef?
    C'est pi-être pas possible?
  • schlumschlum Membre
    21:54 modifié #33
    Je n'utilise jamais CGAffineTransform (trop lourd et mal foutu), il suffit d'appliquer directement les transformations de cette manière :
    - Sauvegarder le contexte
    - Appliquer la transformation
    - Restaurer le contexte

    Mais je suppose que CGAffineTransform permet d'appliquer d'un coup une combinaison de plusieurs transformations élémentaires.
  • GreensourceGreensource Membre
    21:54 modifié #34
    Mais je comprend pas le principe, c'est le contexte que l'on transforme? C'est trop bizarre ça! Pourquoi on change pas plutôt ce qu'on veut dessiner?
  • schlumschlum Membre
    21:54 modifié #35
    dans 1235737971:

    Mais je comprend pas le principe, c'est le contexte que l'on transforme? C'est trop bizarre ça! Pourquoi on change pas plutôt ce qu'on veut dessiner?


    Si tu as fait un peu d'OpenGL, considère que c'est la même chose qu'empiler / dépiler des matrices de transformation...  8--)
    (sauf que là  c'est en 2D, donc carrément plus simple !)
  • GreensourceGreensource Membre
    21:54 modifié #36
    Je crois voir de quoi tu parles, mais c'est pareil, pour moi les transformation on les fait sur l'objet pas sur le contenant de l'objet.
    Mais c'est peut-être moi qui n'ai pas bien compris la doc. Le context, c'est bien le truc dans lequel on va afficher des choses?
    Pour moi mon CGPathRef c'est mon objet et mon context c'est la vue dans laquelle je veux dessiner mon Path? J'ai bon ou pas?
  • schlumschlum Membre
    21:54 modifié #37
    dans 1235738719:

    Je crois voir de quoi tu parles, mais c'est pareil, pour moi les transformation on les fait sur l'objet pas sur le contenant de l'objet.
    Mais c'est peut-être moi qui n'ai pas bien compris la doc. Le context, c'est bien le truc dans lequel on va afficher des choses?
    Pour moi mon CGPathRef c'est mon objet et mon context c'est la vue dans laquelle je veux dessiner mon Path? J'ai bon ou pas?


    Le contexte n'est pas la vue non... C'est plutôt le système de coordonnées utilisées (origine / axes / échelles)
    En gros tu imagines un système de coordonnées avec l'origine en bas à  gauche et une graduation d'1 par pixel (orthonormé donc), et tu appliques des transformations dessus (translation, rotation, homothétie) avant de dessiner ton objet dedans (repère toujours orthogonal, mais plus normé).
  • Philippe49Philippe49 Membre
    21:54 modifié #38
    On peut faire la transformation à  la création avec le deuxième argument des constructeurs

    void CGPathAddArc (
      CGMutablePathRef path,
      const CGAffineTransform *m,
      CGFloat x,
      CGFloat y,
      CGFloat radius,
      CGFloat startAngle,
      CGFloat endAngle,
      bool clockwise
    );
  • AliGatorAliGator Membre, Modérateur
    février 2009 modifié #39
    Oui par contre moi comme Greensource ça m'intéresserait de transformer un CGPath hors de son dessin.

    A la base en général on construit notre CGPath (autour de 0,0) et au moment de le dessiner, on applique une matrice de transformation affine pour se positionner où l'on veut, on dessine, et on remet le contexte.

    Mais y'a des fois où l'on voudrait directement transformer le CGPath.
    - D'une part ça peu être pratique pour éviter de concaténer la CTM à  chaque fois qu'on dessine (un peu une perte de temps cette multiplication de matrice si c'est toujours la même !) ;
    - Mais aussi et surtout pour des méthodes genre containsPoint: pour savoir si un point est dans le CGPath : actuellement j'applique la transformation inverse au point avant de tester s'il est dans mon CGPath, plutôt que d'appliquer la transformation directe au CGPath lui-même... (encore un calcul matriciel inverse qu'on pourrait éviter... bon en général c'est qu'une translation mais pas toujours donc c'est vite prise de tête)... mais si on pouvait transformer une fois pour toutes les CGPath, plus besoin ensuite de modifier la CTM lors du dessin mais et plus besoin de faire la ransfo inverse lors de tests de contenance de point... ce serait plus simple non ?
  • Philippe49Philippe49 Membre
    février 2009 modifié #40
    J'ai bien l'impression qu'une méthode comme transformUsingTransform sur les NSBezierPath reconstruit le path plutôt que de s'amuser à  appliquer la matrice sur chaque élément.

    Ce que je ne retrouve pas, c'est la manière de décomposer un CGPath en éléments qui permettrait de faire une fonction perso CGPathByApplyingTransform(. .) .
  • GreensourceGreensource Membre
    21:54 modifié #41
    Bas ouais ça, ça serait bien, mais CGPath c'est un type opaque, donc on ne peut pas le décomposer c'est le principe non?
  • Philippe49Philippe49 Membre
    21:54 modifié #42
    CGPath est forcément opaque sur les primitives graphiques (tracé de lignes, de courbes de bezier, ...), il pourrait peut-être l'être un peu moins sur le stockage de la suite d'instructions de tracés qu'il représente. ..
    Ceci dit on peut toujours se faire soi-même un wrapper à  la mode de NSBezierPath, et là  on pourra appliquer la transformation. Ma question est plutôt ne réinvente-t-on pas là  quelque chose de déjà  existant dans les CGMutablePathRef ? 
  • GreensourceGreensource Membre
    21:54 modifié #43
    J'ai fouiné un peu l'autre jour mais rien de concluant, je vais essayer de regarder ça plus en profondeur ce soir.
  • GreensourceGreensource Membre
    21:54 modifié #44
    C'est étrange, j'ai une erreur ou la méthode UIGraphicsGetCurrentContext() me rend nil dans la vue? Pourtant dans une vue ça rend forcément le contexte de celle-ci, non?

    Ou alors ça voudrais dire que j'ai vidé la pile des contextes? J'ai pourtant vérifié pour pas faire de bêtise.

    Pour info ça me rend nil uniquement dans les méthodes appelé lorsqu'on touche l'écran (touchBegans ...)

    Vous avez déjà  eu ce genre d'étrangeté?
  • AliGatorAliGator Membre, Modérateur
    21:54 modifié #45
    Le GraphicContext d'une vue n'est créé et ajouté à  la pile de GraphicContexts qu'avant l'appel à  drawRect, et est enlevé de la pile des GC à  la fin de l'appel à  drawRect.
    Donc dans les méthodes touchBegan & co, où il ne faut pas faire d'opération de dessin (car il faut tout centraliser sur drawRect), il n'y a jamais de GraphicContext courant, c'est normal.
  • GreensourceGreensource Membre
    février 2009 modifié #46
    Ah nan!!! C'est le bordel ça! Parce que vois-tu j'ai besoin, dans touchBegans de vérifier dans qu'elle case on a "touché".
    Avec la solution que tu m'as proposé, la HXCell pouvais calculé cela grâce à  l'attribut Path qu'elle contenait.
    Maintenant c'est la vue qui enregistre un "Path" en hexagone et mes cases on seulement des coordonnées.

    Donc il me reste à  trouver comment savoir dans qu'elle case on a cliqué. Je vais bien finir par trouver, merci pour tes infos en tout cas, c'est cool je comprend plein de nouveaux truc!

    Juste comme ça, pédagogiquement je trouve ça pas mal comme technique (je suis étudiant). Je galère pendant un certain temps, ce qui me permet de fouiné dans la doc, les forum...Donc mine de rien j'acquière des connaissances que je n'aurais pas eu autrement. Et puis grâce aux connaissances des membres du forum je ne reste pas bloqué indéfiniment, vraiment c'est très agréable.
  • GreensourceGreensource Membre
    21:54 modifié #47
    Tout à  fait! Je suis bien content de m'être enfin mis moi même à  ce projet. C'est chaud par contre quand on a pas eu trop de base mais c'est d'autant plus gratifiant.

    Bon sinon pour savoir si un point est contenu dans une case j'ai peu être trouver une solution, mais j'en suis pas du tout satisfait dans le principe. J'ai remis une méthode dans ma case qui me dit si un CGPoint est contenu dans ma case. Sauf que pour ça je dois refaire un Path dans cette méthode. C'est pas tiptop vu que je voulais réserver le Path pour la vue.
    D'un autre coté on peut aussi considérer que ça fait partie du Model d'une case mais j'aime pas trop.
  • AliGatorAliGator Membre, Modérateur
    21:54 modifié #48
    Bah sinon pourquoi ne pas garder ton architecture actuelle, le CGPath dans la vue et les cases dans le modèle, sans CGPath de ce côté ?

    Pour savoir si un point est dans une case, il suffit théoriquement de demander (du côté de la vue donc) si, quand on positionne le CGPath aux coordonnées de la case à  tester, le point est dedans.

    Bon le truc, comme on disait plus haut, c'est qu'il ne semble pas possible d'appliquer une AffineTransform (translation en l'occurence) directement à  ton CGPath pour le placer au bon endroit, non pas pour le dessiner mais pour tester si le point est dedans ensuite... Ceci dit, on peut faire l'inverse ! C'est à  dire appliquer la transformation inverse au point à  tester : plutôt que d'appliquer la translation (tx,ty) au CGPath et ensuite vérifier que le point (x,y) se trouve dans le Path translaté, on peut vérifier si le point translaté de (-tx,-ty) est dans le CGPath non translaté (autrement dit si le point (x-tx,y-ty) est contenu dans le CGPath)

    ----

    PS : Pour décomposer un CGPath en éléments il existe une méthode, CGPathApply, qui permet d'appliquer une fonction qui va parcourir chacun des éléments du CGPath. Chaque élément est de type CGPathElement, qui est en fait une structure contenant un CGPathElementType (enum disant s'il s'agit d'une ligne, d'un arc, ...) ainsi qu'un tableau de un ou plusieurs CGPoint (selon le type) pour définir chaque élément composant le CGPath. Cependant, cette méthode CGPathApply ne permet que de parcourir le CGPath existant, pas de le modifier. Mais bon rien n'empêche de passer dans le paramètre "void* info" un CGMutablePathRef qu'on a créé, et de laisser la CGPathApplierFunction remplir ce path en ajoutant les mêmes éléments que ceux du path traveré, mais avec application de la matrice de transformation ;)

    Bon après pour le cas qui intéresse GreenSource (tester si un point est dans un CGPath qui sera translaté lors de son dessin), à  mon avis faire la translation inverse du point plutôt que translater tout le CGPath est largement plus adéquat que de translater tout un CGPath entier ! Mais c'était juste pour vous informer de la possibilité ;)
  • Philippe49Philippe49 Membre
    21:54 modifié #49
    dans 1235771066:

    PS : Pour décomposer un CGPath en éléments il existe une méthode, CGPathApply, qui permet d'appliquer une fonction qui va parcourir chacun des éléments du CGPath. Chaque élément est de type CGPathElement,


    Effectivement, c'est pile ce qu'il faut.
  • GreensourceGreensource Membre
    21:54 modifié #50
    C'est vrai que ça semble moins lourd de translater le context que d'appliquer une fonction à  chaque élément du Path.
    D'ailleurs ça m'amène à  me demander de l'importance d'optimiser mon code dès maintenant. Parce que si je veux un déploiement effectif sur l'iPhone j'ai plutôt toujours intérêt à  choisir la solution la moins coûteuse?
  • GreensourceGreensource Membre
    21:54 modifié #51
    Me revoilà ! Bon les choses avance plutôt bien et à  bon rythme :P
    J'ai bien sur encore plein de question ^^
    Alors voilà , j'ai une vue case qui se charge de dessiner un hexagone et d'écrire à  l'intérieure des infos numérique. Cette vue n'est pas une UIView, elle contient essentiellement un CGPathRef.
    Ce qu'on voudrais c'est afficher l'info numérique non pas sous forme de texte mais de valeur dans une pastille. Exactement comme le fait l'appli Mail avec la petite pastille rouge.
    Le problème c'est que je me demande si je ne me suis pas engagé dans une mauvais voie en ne faisant pas de ma vue case une UIView?
    Le souci c'est qu'il ne me faut pas non plus un truc rectangulaire comme l'UIView l'est (superposage sinon).
    La solution que je voudrais mettre en place:
    Ma vue Case à  aussi un center, je vais donc me basé dessus pour afficher la pastille avec CGImage.
    Puis afficher le texte de l'info numérique au centre de la CGImage.
    C'est une bonne idée selon vous ou bien on peut faire plus simple et/ou plus facile?
    Merci
Connectez-vous ou Inscrivez-vous pour répondre.