IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Composants FMX Delphi Discussion :

Grilles, et tri (visuel dans le titre des colonnes)


Sujet :

Composants FMX Delphi

  1. #1
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 586
    Billets dans le blog
    65
    Par défaut Grilles, et tri (visuel dans le titre des colonnes)
    Bonjour,

    Conscient de la critique de Gilles à propos des grilles FMX et comme j'étais sur ma lancée

    , je me suis un peu plus penché sur la question.

    L'objectif, comment modifier l'entête des colonnes de grille sans pour autant créer un style personnalisé ce qui est souvent rébarbatif.

    Donc, contrairement à ce que j'ai pu initier en 2019 https://www.developpez.net/forums/d1...omiser-grille/ , et reporter dans un billet de mon blog
    j'entame une démarche par code

    Vous ne le saviez peut-être pas, mais il est tout à fait possible :
    • de modifier la hauteur du titre ;
    • de modifier sa présentation ;
    • d'ajouter des composants à un entête de colonne.


    Partant de ce principe, je commence à obtenir des résultats
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    /// Changement de hauteur
    procedure TForm131.btnHeaderSizeClick(Sender: TObject);
    var
      Header: THeader;
    begin
      Header:= THeader(StringGrid1.FindStyleResource('header'));
      Header.Height := 40;
    end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    /// Changement de présentation (globale)
    procedure TForm131.StringGrid1ApplyStyleLookup(Sender: TObject);
    var
      Header: THeader;
      HeaderItem: THeaderItem;
      I: Integer;
    begin
      Header:= THeader((Sender as TStringGrid).FindStyleResource('header'));
      if Assigned(Header) then
        begin
          for I := 0 to pred(Header.Count) do
            begin
              HeaderItem:= Header.Items[I];
              HeaderItem.StyledSettings := HeaderItem.StyledSettings - [TStyledSetting.Size, TStyledSetting.FontColor];
              HeaderItem.Font.Size := 20;
              HeaderItem.FontColor:= TAlphaColors.Blue;
              HeaderItem.TextSettings.HorzAlign := TTextAlign.Center;
              HeaderItem.TextSettings.VertAlign := TTextAlign.Center;
          end;
          Header.Height := 32;
      end;
    end;
    et enfin ajout d'image (ici un tpath)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    procedure TForm131.btnAddPathClick(Sender: TObject);
    var
      Header: THeader;
      HeaderItem: THeaderItem;
    begin
      Header:= THeader(StringGrid1.FindStyleResource('header'));
      if assigned(Header) then HeaderItem:= Header.Items[0];
     
      with Tpath.Create(HeaderItem) do
       begin
         Align:=TalignLayout.Right;
         Parent:=HeaderItem;
         HeaderItem.TextSettings.HorzAlign := TTextAlign.Leading;
         Data.Data:='M3 13H15V11H3M3 6V8H21V6M3 18H9V16H3V18M22.54 16.88L20.41 19L22.54 21.12'+
                    'L21.12 22.54L19 20.41L16.88 22.54L15.47 21.12L17.59 19L15.47 16.88'+
                    'L16.88 15.47L19 17.59L21.12 15.46L22.54 16.88';
         Width:=Header.Height;
         OnClick:=ClickSort;
       end;
    end;
    Nom : Capture.PNG
Affichages : 548
Taille : 10,6 Ko
    en encadré, ce que j'envisage comme présentation de la partie tri (j'ai opté pour un GridPanelLayout contenant un label pour l'ordre de tri et 3 TPath, l'événement à gérer sera le onclick du GridPanelLayout)

    Pour aller plus loin et rendre les choses plus faciles je me suis même mis en tête de créer un Helper (ma marotte du moment)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     TColumnHelpers = Class helper for TCustomGrid
      public
        procedure SetAColumnAsSortable(const Column : TColumn; const HeaderHeight : Single =0 );
        function IsColumnSortable(const Column : TColumn) : Boolean;
      end;
    Voilà (enfin) ma question, il va me falloir accéder à des propriétés (ce qu'un helper ne permet pas), évènements et fonctions spécifiques, pour ne pas avoir à modifier le composant, je songeais utiliser le tagobject de chaque colonne avant de me lancer dans cette aventure, est-ce possible ?

  2. #2
    Membre Expert
    Avatar de pprem
    Homme Profil pro
    MVP Embarcadero - formateur&développeur Delphi, PHP et JS
    Inscrit en
    Juin 2013
    Messages
    1 876
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : MVP Embarcadero - formateur&développeur Delphi, PHP et JS
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2013
    Messages : 1 876
    Par défaut
    Utiliser le TagObject est une solution mais normalement les propriétés "tag" sont réservées au développeur final et ne devraient pas être modifiées dans les composants.

    Là, à toi de voir si tu fermes l'accès à cette propriété pour les développeurs qui utiliseront ton code. Après tout c'est une approche qui te permet de faire tes essais sans trop te prendre la tête, donc je dirais GO.

    L'autre solution que tu peux tenter, que j'appelle généralement "l'astuce de Paul Toth" (puisque c'est de lui que je la tiens et que je n'y avais pas pensé avant), c'est de surcharger la classe en l'appelant avec le même nom pour ajouter des fonctionnalités en code sans avoir à réimporter le composant dans l'IDE (par contre ton unité contenant le code devra être chargée en dernier dans l'interface de l'unité qui utilise la grille).

    un truc du style:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    type
    TGrid = class(FRM.JeNeSaisPlusQuelleUnite.TGrid)
    end;

  3. #3
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 586
    Billets dans le blog
    65
    Par défaut
    surcharger la classe en l'appelant avec le même nom pour ajouter des fonctionnalités en code
    ce truc-là, je l'envisage aussi (je ne savais pas que Paul en avait fait un "truc"), c'est ce que j'entends aussi par dériver le composant de base.
    Je l'ai déjà fait pour je ne sais plus quel composant ni dans quelles circonstances

    tu fermes l'accès à cette propriété pour les développeurs qui utiliseront ton code.
    exact, mais qui utilise tagobject

  4. #4
    Membre Expert
    Avatar de pprem
    Homme Profil pro
    MVP Embarcadero - formateur&développeur Delphi, PHP et JS
    Inscrit en
    Juin 2013
    Messages
    1 876
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : MVP Embarcadero - formateur&développeur Delphi, PHP et JS
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2013
    Messages : 1 876
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    exact, mais qui utilise tagobject
    euh... moi

  5. #5
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 586
    Billets dans le blog
    65
    Par défaut
    Après avoir longtemps galéré sur le dessin (https://www.developpez.net/forums/d2...ayout-runtime/)

    J'arrive au bout de la méthode utilisée à base de Helpers et de l'utilisation d'un "simple" TagObject. De plus en plus complexe, il est évident qu'une "surclasse" du composant serait plus facile.
    Nom : Capture.PNG
Affichages : 471
Taille : 48,8 Ko

    En effet, même s'il me reste quelques petits bogues (ordre du tri, largeur du gridpanellayout), c'est surtout la question application du tri sur lequel je m'attache aujourd'hui.

    Plusieurs questions restent en suspens :
    - déclencher le tri
    - trier un tableau (stringgrid) s'il n'est pas lié à une source de données, plus exactement s'il s'agit d'un remplissage par code ou par liaisons d'objets (prototypebindsource et oncreateADapter pour les "vrais objets".
    N.B. si le tableau est lié, je n'ai envisagé qu'une liaison à une source de données Firedac permettant d'utiliser IndexFieldNames. En parlant de ceci, toujours en clin d'œil à Gilles , il serait aussi possible d'ajouter un Combobox ou un Searchbox, selon la même technique que pour le tri et d'utiliser la propriété Filter des sources de données Firedac.

    un petit retour sur le code de mon TagObject
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     TGridObject = class
      private
        FGridSelectedRange: TRect;
        FGridSelectedCols: TList<Integer>;
        FGridSelectedRows: TList<Integer>;
        FGridSelColor: TAlphaColor;
        FGridSelOpacity: Single;
        FGridHeaderBrush : TBrush;
        FGridHeaderStrokeBrush : TStrokeBrush;
        FGridSelBrush : TBrush;
        FSelectionMode : TGridSelectionMode;
        FOwner: TStringGrid;
        FSortableColumns: TList<TColumn>;
        FSortedColumns: integer;
        procedure SetGridSelOpacity(const Value: Single);
        procedure SetGridSelColor(const Value: TAlphaColor);
        procedure SetSortedColumns(const Value: integer);
      public
       property GridSelColor  : TAlphaColor read FGridSelColor;
       property GridSelOpacity  : Single read FGridSelOpacity write SetGridSelOpacity;
       property GridSelectedCols : TList<Integer> read FGridSelectedCols; // write SetGridSelectedCols;
       property GridSelectedRows : TList<Integer> read FGridSelectedRows; // write SetGridSelectedRows;
       property GridSelectedRange : TRect read FGridSelectedRange;  // write SetGridSelectedRange;
       property GridSelBrush : TBrush read FGridSelBrush;
       property GridHeaderBrush : TBrush read FGridHeaderBrush;
       property GridHeaderStrokeBrush : TStrokeBrush read FGridHeaderStrokeBrush;
       property SelectionMode : TGridSelectionMode read FSelectionMode;
       property SortableColumns : TList<TColumn> read FSortableColumns;
       property SortedColumns : integer read FSortedColumns write SetSortedColumns;
       property Owner : TStringGrid read FOwner; // write Setowner;
       constructor Create(Owner : TStringGrid);
      end;
    Tout d'abord, je me heurte à l'ordre de ma liste de colonnes "triables" SortableColumns, il faudrait qu'elle soit triée en ordre ascendant en fonction du tag de l'entête de colonne (mauvais choix, je pense, j'aurai certainement dû utiliser le tag de colonne. Facile à corriger). Bon, étant donné que c'est un TList<TColumn> ce n'est qu'un peu de code de tri à écrire donc solvable.

    Le tri d'une liaison à des objets (OnCreateAdapter) puisqu'un TList<unobjet> sera utilisé, c'est encore gérable, quoi que je n'aie, jusqu'à présent, codé des tris que sur un seul critère.
    Le tri d'un tableau non lié ou d'un TPrototypeBindSource, par contre, je ne sais pas vraiment par quel bout commencer

  6. #6
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 586
    Billets dans le blog
    65
    Par défaut
    Des recherches pour une autre personnalisation des cellules m'ont fait découvrir une unité FMX.Grid.Style
    Quelqu'un a déjà utilisé et si oui comment faire ?

    J'y vois de gros élagages s'il est possible d'utiliser cette unité en exemple la propriété HeaderItem[const Index: Integer]

  7. #7
    Membre Expert
    Avatar de pprem
    Homme Profil pro
    MVP Embarcadero - formateur&développeur Delphi, PHP et JS
    Inscrit en
    Juin 2013
    Messages
    1 876
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : MVP Embarcadero - formateur&développeur Delphi, PHP et JS
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2013
    Messages : 1 876
    Par défaut
    malheureusement elle ne simplifie rien aux opérations, c'est utilisé en interne par l'affichage des grilles sous forme de style

  8. #8
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 586
    Billets dans le blog
    65
    Par défaut
    Je reprends le fil de cette discussion après des évolutions imprévues suite à la discussion récente initiée par navig
    en résumé j'en étais à ce stade : la possibilité d'utiliser un seul TSKSVG (faut oser )

    Nom : Capture.PNG
Affichages : 265
Taille : 5,0 Ko

    Donc dans la suite de cette discussion voici mes objectifs :
    1. Améliorer l'utilisation du SVG via l'utilisation de "variables" traitées via des remplacements de chaines.
    2. Continuer la piste du helper.
    3. Me pencher (enfin) sur la partie tri.
    4. Finalement, pourquoi pas tant que l'on y est ajouter une recherche via un TEdit et dans l'absolu compléter ce dernier par une liste des valeurs possibles (à la mode tableur).



    Les objectifs sont nombreux, je ne sais pas si je les tiendrai tous n'ayant aucune urgence professionnelle

    un préalable : il faudra désormais une version 12.1 minimum (ce qui tombe à pic car la version community en est à ce stade)
    Pourquoi ?
    Tout d'abord pour l'utilisation du multistring pour la déclaration du SVG, je suis feignant , cependant cela ôte la possibilité d'ajouter des commentaires
    Je ne sais pas trop ce que cela apporte niveau dessin (mes précédents posts étant fait avec une version plus ancienne 10.1)
    Il y a une histoire de THeader avec la version 12.1, du moins d'après mes souvenirs de note de version (si quelqu'un a des infos dessus, merci de m'en faire part, je n'avais pas suivi l'affaire)
    C'est surtout pour le dernier point que la version 12.1 et son QBE me semble nécessaire (évitant ainsi des manipulations du Datasource de départ j'espère)

    Et voilà le résultat partiel pour l'objectif 1
    Nom : Capture.PNG
Affichages : 267
Taille : 6,3 Ko
    le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    procedure TForm1.Grid1DrawColumnHeader(Sender: TObject; const Canvas: TCanvas;
      const Column: TColumn; const Bounds: TRectF);
    var
      Header: THeader;
      HeaderItem: THeaderItem;
      svgfinal : String;
     
    const svgsort = '''
        <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 511.993 511.993" xml:space="preserve" fill="#000000">
        <g>
        <rect x="0.000" y="0.362" style="fill:#00A1A7;" width="100.000" height="73.038"></rect>
        <rect x="0.000" y="146.444" style="fill:#00A1A7;" width="150.000" height="73.038"></rect>
        <rect x="0.000" y="292.519" style="fill:#00A1A7;" width="250.000" height="73.038"></rect>
        <rect x="0.000" y="438.594" style="fill:#00A1A7;" width="300.000" height="73.038"></rect>
        </g>
        <circle cx="400" cy="100" r="100" style="stroke:none; fill:red" />
        <text x="370" y="150" style="font-family: Times New Roman;
                       font-size  : 150;
                       fill       : white;">$TRI</text> 
        <g>
        </g>
        </svg>
    ''';
     
     
    begin
      svgfinal:=svgsort;
      svgfinal:=StringReplace(svgfinal,'fill:#00A1A7;','fill:green;',[rfreplaceall]);
      Header:= THeader(Grid1.FindStyleResource('header'));
      if assigned(Header) then HeaderItem:= Header.Items[column.index] else exit;
     
    case Column.Index of
      0 : begin
       if HeaderItem.ComponentCount>1 then HeaderItem.Components[1].Destroy;
     
       with TSKSvg.Create(HeaderItem) do
       begin
         Margins.Right:=2;
         Margins.Top:=1;
         Margins.Bottom:=1;
         Height:=Header.Height-2;
         Width:=Height;
         Align:=TalignLayout.Right;
         Parent:=HeaderItem;
         HeaderItem.TextSettings.HorzAlign := TTextAlign.Leading;
         SvgFinal:=StringReplace(svgfinal,'$TRI',(Column.Index+1).toString,[]);  // bien sûr ce n'est pas la valeur de l'ordre de tri, ici c'est juste une test 
     
         SVG.Source:=svgfinal;
     
         Width:=Header.Height;
    //     OnClick:=ClickSort;
       end;
      end;
      1 : begin
       if HeaderItem.ComponentCount>1 then HeaderItem.Components[1].Destroy;
       with TSKSvg.Create(HeaderItem) do
       begin
         Margins.Right:=2;
         Margins.Top:=1;
         Margins.Bottom:=1;
         Height:=Header.Height-2;
         Width:=Height;
         Align:=TalignLayout.Right;
         Parent:=HeaderItem;
         HeaderItem.TextSettings.HorzAlign := TTextAlign.Leading;
         SVGfinal:=StringReplace(SVGfinal,'$TRI',(Column.Index+1).toString,[]);  // bien sûr ce n'est pas la valeur de l'ordre de tri, ici c'est juste une test 
         SVG.Source:=svgfinal;
         Width:=Header.Height;
    //     OnClick:=ClickSort;
       end;
     end;
    end;
    commentaires sur mon SVG, pour l'instant je n'ai utilisé qu'une seule "variable" $TRI
    <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlnslink="http://www.w3.org/1999/xlink" viewBox="0 0 511.993 511.993" xml:space="preserve" fill="#000000">
    <g>
    // remplacement de la valeur y pour l'ordre descendant
    // remplacement de la couleur fill:#00A1A7; au besoin
    <rect x="0.000" y="0.362" style="fill:#00A1A7;" width="100.000" height="73.038"></rect>
    <rect x="0.000" y="146.444" style="fill:#00A1A7;" width="150.000" height="73.038"></rect>
    <rect x="0.000" y="292.519" style="fill:#00A1A7;" width="250.000" height="73.038"></rect>
    <rect x="0.000" y="438.594" style="fill:#00A1A7;" width="300.000" height="73.038"></rect>
    </g>
    <circle cx="400" cy="100" r="100" style="stroke:none; fill:red" /> // fil:red devra être fill:none si non utilisée, fill:<valeur> si besoin
    <text x="370" y="150" style="font-family: Times New Roman;
    font-size : 150;
    fill : white;">$TRI</text> // ma variable
    <g>
    </g>
    </svg>
    J'attends vos suggestions

    une critique cependant cette fonctionnalité n'est visible qu'au runtime, au temps pour le wyseewyg intégrer ça de façon à l'obtenir demandera au minimum la création d'un composant (,d'un style ?) et je nse sais quoi d'autre mais passons déjà les premières étapes

  9. #9
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 586
    Billets dans le blog
    65
    Par défaut mi-parcours, objectif 1
    Il reste des peaufinages, mais à mi-parcours de la matinée voici le résultat
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    procedure TForm1.Grid1DrawColumnHeader(Sender: TObject; const Canvas: TCanvas;
      const Column: TColumn; const Bounds: TRectF);
    var
      Header: THeader;
      HeaderItem: THeaderItem;
     
    function typetri(tritype : smallint) : string;  // todo ajouter valeur par défaut 0 pour tritype et couleurs (traits, cercle)
    // tritype contient le sens si >0 DESC si<0 ASC  et l'ordre de tri 
    const svgsort = '''
        <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 511.993 511.993" xml:space="preserve" fill="#000000">
        <g color="#00A1A7">
        <rect x="0.000" y="$T1"  fill="currentColor" width="100.000" height="73.038"></rect>
        <rect x="0.000" y="$T2"  fill="currentColor" width="150.000" height="73.038"></rect>
        <rect x="0.000" y="$T3"  fill="currentColor" width="250.000" height="73.038"></rect>
        <rect x="0.000" y="$T4"  fill="currentColor" width="300.000" height="73.038"></rect>
        </g>
        <circle cx="400" cy="$CPOS" r="100" style="stroke:none; fill:$CFIL" />
        <text x="370" y="$TPOS" style="font-family: Times New Roman;
                       font-size  : 150;
                       fill       : white;">$TRI</text>
        <g>
        </g>
        </svg>
    ''';
     begin
       result:=svgsort;
       if tritype=0 then
        begin
         result:=StringReplace(result,'$T1','146.444',[]);
         result:=StringReplace(result,'$T2','0.362',[]);
         result:=StringReplace(result,'$T3','438.594',[]);
         result:=StringReplace(result,'$T4','292.519',[]);
         result:=StringReplace(result,'g color="#00A1A7"','g color="silver"',[rfreplaceall]);
         result:=StringReplace(result,'$CFIL','none',[]);
         result:=StringReplace(result,'$TRI','',[]);
        end
       else begin
         if tritype>0 then begin
         // type de tri Descendant
         result:=StringReplace(result,'$T1','0.362',[]);
         result:=StringReplace(result,'$T2','146.444',[]);
         result:=StringReplace(result,'$T3','292.519',[]);
         result:=StringReplace(result,'$T4','438.594',[]);
         result:=StringReplace(result,'$CFIL','red',[]);
         result:=StringReplace(result,'$CPOS','100',[]);
         result:=StringReplace(result,'$TPOS','150',[]);
         result:=StringReplace(result,'$TRI',tritype.ToString,[]);
         end
         else begin
        // type de tri Ascendant
         result:=StringReplace(result,'$T1','438.594',[]);
         result:=StringReplace(result,'$T2','292.519',[]);
         result:=StringReplace(result,'$T3','146.444',[]);
         result:=StringReplace(result,'$T4','0.362',[]);
         result:=StringReplace(result,'$CFIL','red',[]);
         result:=StringReplace(result,'$CPOS','400',[]);
         result:=StringReplace(result,'$TRI',Abs(tritype).ToString,[]);
         result:=StringReplace(result,'$TPOS','450',[]);
         end;
       end;
     end;
     
    begin
    //  svgfinal:=svgsort;
    //  svgfinal:=StringReplace(svgfinal,'fill:#00A1A7;','fill:green;',[rfreplaceall]);
      Header:= THeader(Grid1.FindStyleResource('header'));
      if assigned(Header) then HeaderItem:= Header.Items[column.index] else exit;
     
    case Column.Index of
      0 : begin
       if HeaderItem.ComponentCount>1 then HeaderItem.Components[1].Destroy;
     
       with TSKSvg.Create(HeaderItem) do
       begin
         Margins.Right:=2;
         Margins.Top:=1;
         Margins.Bottom:=1;
         Height:=Header.Height-2;
         Width:=Height;
         Align:=TalignLayout.Right;
         Parent:=HeaderItem;
         HeaderItem.TextSettings.HorzAlign := TTextAlign.Leading;
         SVG.Source:=typetri(1);
         Width:=Header.Height;
    //     OnClick:=ClickSort;
       end;
      end;
      1 : begin
       if HeaderItem.ComponentCount>1 then HeaderItem.Components[1].Destroy;
       with TSKSvg.Create(HeaderItem) do
       begin
         Margins.Right:=2;
         Margins.Top:=1;
         Margins.Bottom:=1;
         Height:=Header.Height-2;
         Width:=Height;
         Align:=TalignLayout.Right;
         Parent:=HeaderItem;
         HeaderItem.TextSettings.HorzAlign := TTextAlign.Leading;
         SVG.Source:=typetri(-2);
         Width:=Header.Height;
    //     OnClick:=ClickSort;
       end;
       end;
      2 : begin
       if HeaderItem.ComponentCount>1 then HeaderItem.Components[1].Destroy;
       with TSKSvg.Create(HeaderItem) do
       begin
         Margins.Right:=2;
         Margins.Top:=1;
         Margins.Bottom:=1;
         Height:=Header.Height-2;
         Width:=Height;
         Align:=TalignLayout.Right;
         Parent:=HeaderItem;
         HeaderItem.TextSettings.HorzAlign := TTextAlign.Leading;
         SVG.Source:=typetri(0);
         Width:=Header.Height;
    //     OnClick:=ClickSort;
       end;
     end;
    end;
    Nom : Capture.PNG
Affichages : 269
Taille : 11,8 Ko

    quelques explications :
    le bouton permet d'augmenter la taille du header

    la colonne hello est triée en premier en ordre DESCendant
    la colonne world est triée en second en ordre ASCendant
    à moins que je ne sois dyslexique et que ce soit l'inverse

    et enfin la dernière colonne n'est pas triée mais pourrait l'être

  10. #10
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 586
    Billets dans le blog
    65
    Par défaut Suite
    Quelque chose ne me plaisait pas dans mon code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      if HeaderItem.ComponentCount>1 then HeaderItem.Components[1].Destroy;
    j'ai remplacé par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     for var aSVG in HeaderItem.Children do if (aSVG is TSkSvg) then aSVG.Destroy;
    Encore que je ne comprenne pas trop pourquoi je dois détruire, il y a certainement mieux, mais j'ai fait la constatation que, si non, j'avais plusieurs SVG pour un même Header

    Ensuite j'ai voulu bruler les étapes et passer à la 4, l'ajout d'un TEdit et là je "tombe" sur 2 os
    Nom : Capture.PNG
Affichages : 262
Taille : 4,3 Ko
    une nouvelle fois 2 SVG et un Edit un peu à revoir niveau alignement (j'ai fait ça à l'arrache)
    mais c'est surtout le deuxième os qui me met dans la panade : on ne peut pas saisir quoique ce soit dans la zone d'édition

    Même si j'ai, bien sûr, une autre piste, ça fait mal !

    je repars donc sur mon planning le traitement du Onclick sur le SVG
    Nom : Capture.PNG
Affichages : 255
Taille : 12,4 Ko
    et donc, le tri

  11. #11
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 586
    Billets dans le blog
    65
    Par défaut Avancée des travaux
    Hier, je me suis heurté à la limite des Helpers : pas de propriétés, comme j'avais déjà pu le constater précédemment.

    Avant de passer à un composant je me suis mis en tête d'utiliser un cadre (TFrame), bonne idée ou pas ce serait sujet à un débat sur le comment créer un composants FMX

    Toujours est-il que j'obtiens pour l'instant des résultats identiques (si ce n'est la customisation de la couleur des barres et cercle que je n'ai pas encore travaillée)
    Nom : Capture.PNG
Affichages : 231
Taille : 19,0 Ko

    voici l'unité pour la frame
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    unit GrilleFrame;
     
    interface
     
    uses
      System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
      System.Generics.Collections,
      FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls,
      System.Rtti, FMX.Grid.Style, FMX.Grid, FMX.Controls.Presentation,
      FMX.ScrollBox, FMX.Header;
     
    type
      TFrame5 = class(TFrame)
        Grid1: TGrid;
        Column1: TColumn;
        Column2: TColumn;
        Column3: TColumn;
        Column4: TColumn;
        Label1: TLabel;
        procedure Grid1DrawColumnHeader(Sender: TObject; const Canvas: TCanvas;
          const Column: TColumn; const Bounds: TRectF);
      private
     
        FSortList: TDictionary<TColumn,smallint>;
        FColumnSortedList: TList<TColumn>;
        Fgridheaderheight: Integer;
        procedure Setgridheaderheight(const Value: Integer);
        { Déclarations privées }
        function DrawSVGInHeader(aColumn : TColumn;  TriType : integer;
                                 ColorBar:String ='"#00A1A7"';
                                 CircleColor : String='red') : String;
     
      public
        Constructor Create(AOwner:TComponent);Override;
        Destructor Destroy; Override;
        property SortList : TDictionary<TColumn,smallint> read FSortList;
        property gridheaderheight : Integer read Fgridheaderheight write Setgridheaderheight;
        procedure AddToSort(aColumn : TColumn);
        procedure RemoveFromSort(aColumn : TColumn);
        procedure SetColumnSortable(AColumn : TColumn; SortType : integer =0 ;  Sorted : Boolean = True);
        procedure ChangeColumnSort(AColumn : TColumn);
      end;
     
    implementation
     
    {$R *.fmx}
     
    uses  System.Skia, FMX.Skia;
     
    const
      svgsort = '''
        <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg"
        xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 511.993 511.993"
        xml:space="preserve" fill="#000000">
        <g color="#00A1A7">
        <rect x="0.000" y="$T1"  fill="currentColor" width="100.000" height="73.038"></rect>
        <rect x="0.000" y="$T2"  fill="currentColor" width="150.000" height="73.038"></rect>
        <rect x="0.000" y="$T3"  fill="currentColor" width="250.000" height="73.038"></rect>
        <rect x="0.000" y="$T4"  fill="currentColor" width="300.000" height="73.038"></rect>
        </g>
        <circle cx="400" cy="$CPOS" r="100" style="stroke:none; fill:$CFIL" />
        <text x="370" y="$TPOS" style="font-family: Times New Roman;
                       font-size  : 150;
                       fill       : white;">$TRI</text>
        <g>
        </g>
        </svg>
      ''';
     
    { TFrame5 }
     
    procedure TFrame5.AddToSort(aColumn : TColumn);
    begin
    if not FSortList.ContainsKey(aColumn) then FSortList.Add(aColumn,0);
    end;
     
    procedure TFrame5.ChangeColumnSort(AColumn : TColumn);
    begin
     
    end;
     
    constructor TFrame5.Create(AOwner: TComponent);
    var
      I: Integer;
    begin
      inherited;
      FSortList:=TDictionary<TColumn,smallint>.Create;
      FColumnSortedList:= TList<TColumn>.Create();
      gridheaderheight:=40;
    end;
     
    destructor TFrame5.Destroy;
    begin
      FSortList.Free;
      FColumnSortedList.Free;
      inherited;
    end;
     
    function TFrame5.DrawSVGInHeader(aColumn: TColumn; TriType : integer; ColorBar:String ='"#00A1A7"'; CircleColor : String='red'): String;
    begin
        result := svgsort;
        if tritype = 0 then
        begin
          result := StringReplace(result, '$T1', '146.444', []);
          result := StringReplace(result, '$T2', '0.362', []);
          result := StringReplace(result, '$T3', '438.594', []);
          result := StringReplace(result, '$T4', '292.519', []);
          result := StringReplace(result, 'g color="#00A1A7"', 'g color="silver"',
            [rfreplaceall]);
          result := StringReplace(result, '$CFIL', 'none', []);
          result := StringReplace(result, '$TRI', '', []);
        end
        else
        begin
          if tritype > 0 then
          begin
            // type de tri Descendant
            result := StringReplace(result, 'g color="#00A1A7"', 'g color='+ColorBar,[]);
            result := StringReplace(result, '$T1', '0.362', []);
            result := StringReplace(result, '$T2', '146.444', []);
            result := StringReplace(result, '$T3', '292.519', []);
            result := StringReplace(result, '$T4', '438.594', []);
            result := StringReplace(result, '$CFIL', circlecolor, []);
            result := StringReplace(result, '$CPOS', '100', []);
            result := StringReplace(result, '$TPOS', '150', []);
            result := StringReplace(result, '$TRI', tritype.ToString, []);
          end
          else
          begin
            // type de tri Ascendant
            result := StringReplace(result, 'g color="#00A1A7"', 'g color='+ColorBar,[]);
            result := StringReplace(result, '$T1', '438.594', []);
            result := StringReplace(result, '$T2', '292.519', []);
            result := StringReplace(result, '$T3', '146.444', []);
            result := StringReplace(result, '$T4', '0.362', []);
            result := StringReplace(result, '$CFIL', CircleColor, []);
            result := StringReplace(result, '$CPOS', '400', []);
            result := StringReplace(result, '$TRI', Abs(tritype).ToString, []);
            result := StringReplace(result, '$TPOS', '450', []);
          end;
        end;
     
    end;
     
    //procedure TFrame5.DrawSGVInHeader(aColumn: TColumn) : String;
    //begin
     
    //end;
     
    procedure TFrame5.Grid1DrawColumnHeader(Sender: TObject; const Canvas: TCanvas;
      const Column: TColumn; const Bounds: TRectF);
    var Header : THeader;
        aSVG : TSKSVG;
        sortvalue : smallint;
    begin
      Header:=THeader(Grid1.FindStyleResource('header'));
      if Header.Height<>Fgridheaderheight then Header.Height:=Fgridheaderheight;
      // dessin SVG
      if FColumnSortedList.Contains(Column) then
        begin
          if not FSortList.TryGetValue(Column,sortvalue) then sortvalue:=0;
          var HeaderItem := Header.Items[Column.index];
          aSVG:=nil;
          for var aFMXObj in HeaderItem.Children do
                if (aFMXObj is TSkSvg) then
                 begin
                   aSVG:=TSKSVG(aFMXObj);
                   break;
                 end;
          if not assigned(aSVG) then
            begin
            aSVG:=TSkSvg.Create(HeaderItem);
            with aSVG do
            begin
              Margins.Right := 2;
              Margins.Top := 1;
              Margins.Bottom := 1;
              height := Header.height - 2;
              width := height;
              Align := TalignLayout.Right;
              Parent := HeaderItem;
              HitTest := true;
              HeaderItem.TextSettings.HorzAlign := TTextAlign.Leading;
              svg.Source := DrawSVGInHeader(Column,Sortvalue);
              aSvg.InvalidateRect(TRectF.Create(0,0,height,width));
    //          OnClick := ClickSort;
            end;
            end;
        end;
     
    end;
     
    procedure TFrame5.RemoveFromSort(aColumn : TColumn);
    begin
    FSortList.Remove(aColumn);
    end;
     
    procedure TFrame5.SetColumnSortable(AColumn : TColumn; SortType : integer =0 ;  Sorted : Boolean = True);
    begin
    if Sorted then
      begin
        if not FColumnSortedList.Contains(aColumn) then FColumnSortedList.Add(AColumn);
        if SortType<>0 then FSortList.AddOrSetValue(aColumn,sorttype);
        DrawSVGInHeader(AColumn,SortType);
        Grid1.NeedStyleLookup;
      end
      else
      begin
        if FSortList.ContainsKey(aColumn) then Fsortlist.Remove(aColumn);
        if FColumnSortedList.Contains(aColumn) then FColumnSortedList.Remove(aColumn);
      end;
     
    end;
     
    procedure TFrame5.Setgridheaderheight(const Value: Integer);
    var Header : THeader;
    begin
      Fgridheaderheight := Value;
    end;
     
    end.
    et son utilisation
    procedure TForm1.Button2Click(Sender: TObject);
    begin
    TFrame5(Frame51).gridheaderheight:=40;
    TFrame5(Frame51).SetColumnSortable(TFrame5(Frame51).Column1,1);
    TFrame5(Frame51).SetColumnSortable(TFrame5(Frame51).Column2,-2);
    TFrame5(Frame51).SetColumnSortable(TFrame5(Frame51).Column3,0);
    end;
    Je le concède j'ai quelques renommages et commentaires à faire

    Je butte désormais sur l'ordre de tri.
    J'ai créé un dictionnaire FSortList: TDictionary<TColumn,smallint>; où le smallint serait
    1 - DESC
    0 - pas de tri
    -1 - ASC
    et je pensais utiliser l'index de la colonne dans la liste pour obtenir le numéro d'ordre, quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    numerodordre=valeurlapaire*indexdelapaire
    sauf que l'index je ne sais pas trop comment l'obtenir, une idée ?
    Peut-être dois-je utilisé autre chose une Queue une Pile ou ??

  12. #12
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 488
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 488
    Par défaut
    salut

    tes constantes de tris ne pourrait tu pas faire un truc du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Type 
       TSortDirection = (sdNone, sdDescending, sdAscending);
     
    ....
    procedure DrawOrderFleche(Sender: TObject;Afont : Tfont;Rect : Trect;Sort : TSortDirection);
    Procedure OrderQuery(Column : TColumn;Sort : TSortDirection);
    Procedure OrderGrille(Column : TColumn;Sort : TSortDirection);
     
    ...
    dans le corps du programme quant tu as besoin de connaitre la position
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    ...
      if sort = sdAscending Then
        ...
      else
       if sort = sdDescending Then
         ...
    je ne sais pas pour toi mais perso je trouve cela plus parlant

  13. #13
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 586
    Billets dans le blog
    65
    Par défaut
    Bonjour et merci,

    alors, comme je l'ai écrit ce n'est encore qu'une ébauche et depuis, je suis effectivement passé par une énumération pour le tri (les grands esprits etc...)

    Je ne vais pas, je pense, publier aujourd'hui quoique ce soit vu mon emploi du temps.
    je pense que je vais seulement :
    - jouer avec les couleurs
    - peaufiner ma routine (OnClick sur le SVG) pour l'ordre de tri
    ce que je peux écrire puisque fait hier c'est que j'ai changer quelque peu mes listes, ce qui m'a permis (enfin) d'obtenir ce que j'attendais niveau ordre de tri
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    type
      TSortType = (Asc,None,Desc);  // pour obtenir un index de tri j'utiliserai <span style="font-family: monospace; padding: 2px; background: #ddd; display: inline-block"> ord<span class="br0">(</span>typetri<span class="br0">)</span>-<span style="color: #cc66cc;">1</span></span> ce qui m'évitera de trop changer mes routines de dessin 
     
      TDrawObject = Class(TObject)
      private
        FOrder: TSortType;
        Barcolor : TColor;
        CircleColor : TColor;
       // todo circletextcolor 
        procedure SetOrder(const Value: TSortType);
      published
        property Order : TSortType read FOrder write SetOrder;
     
      public
          Constructor Create(order : TSortType = TSortType.None;
                          bcolor : TColor = $00A1A7;
                          CColor : TColor = TColors.Red);
      End;
     
     
      TFrame5 = class(TFrame)
        Grid1: TGrid;
        Column1: TColumn;
        Column2: TColumn;
        Column3: TColumn;
        Column4: TColumn;
        Label1: TLabel;
        procedure Grid1DrawColumnHeader(Sender: TObject; const Canvas: TCanvas;
          const Column: TColumn; const Bounds: TRectF);
      private
     
        FSortList: TList<TColumn>;
        FColumnSortedList: TDictionary<TColumn,TDrawObject>;
    Ce que je crains : les fuites mémoires que je n'ai pas encore traitées

    Autre chose me tracasse un peu, je ne suis pas sûr à 100% que cela fonctionnerait pour un StringGrid et dans tous les cas, je suis parti bille en tête sur une grille lièe à des données avec colonnes déclarées.
    Finalement, je vais peut-être voir aussi une version avec création de style au runtime si je retrouve certaines de mes ébauches (contrairement à Patrick je ne suis pas un fan des mises à jour de dépôt à chaque modification )

    Un composant dont le nom serait TGovelSortedGrid (Govel=forge en breton) s'ébauche dans mon esprit mais avec encore beaucoup de ramifications imprévues :
    - possibilité de surcharge du onDrawItemHeader
    - possibilité de changer pour un SVG défini à la conception
    - en faire un wyseewyg
    ...

  14. #14
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 586
    Billets dans le blog
    65
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    Il y a une histoire de THeader avec la version 12.1, du moins d'après mes souvenirs de note de version (si quelqu'un a des infos dessus, merci de m'en faire part, je n'avais pas suivi l'affaire)
    Je me réponds, il y a bien eu des nouveautés à retrouver en bas de ce chapitre
    je cite :
    Une nouvelle propriété HeaderSettings pour la classe TColumn a été ajoutée pour que les utilisateurs puissent spécifier le style de l'en-tête de colonne. Cela inclut aussi une nouvelle propriété HeaderStyleLookup.
    Aucune documentation sur ces propriétés
    Nom : Capture.PNG
Affichages : 199
Taille : 10,3 Ko
    résultat (rapide)
    Nom : Capture.PNG
Affichages : 200
Taille : 1,7 Ko
    Après expérience(s) faire attention aux propriétés StyleSettings, j'ai du en raté une sur la fonte car le texte est horizontalement aligné centre alors qu'il est indiqué leading dans les propriétés HeaderSettings.TextSettings
    mea culpa c'est mon style qui n'était pas bon, la propriété StyleName n'avait pas été renommée en Text
    Nom : Capture.PNG
Affichages : 200
Taille : 2,7 Ko

    Conclusion : un casse tête de résolu pour peu de vouloir passer par les styles , sujet à peaufiner en vue d'un billet blog

    pour le Onclick sur le SVG par contre, je suis, pour l'instant, très pensif

  15. #15
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2007
    Messages
    400
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 400
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    Il y a une histoire de THeader avec la version 12.1, du moins d'après mes souvenirs de note de version (si quelqu'un a des infos dessus, merci de m'en faire part, je n'avais pas suivi l'affaire)
    Pour le Theader, j'ai cherché un moment pourquoi un de mes précédents programmes ne fonctionnait plus correctement après compilation sous 12.1 CE.
    Je faisait des mises en forme du THeader en allant chercher les informations par FindStyleResource<THeader> :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    if sg.FindStyleResource<THeader>('Header', h) then
       begin
       h.Height:=22;
       for i:=0 to h.count-1 do
          begin
          ti:=theaderitem(h.items[i]);
          ti.TextSettings.HorzAlign:=ttextAlign.center;
          ti.TextSettings.Trimming:=TTextTrimming(0);
          ti.TextSettings.WordWrap:=true;
          ti.textsettings.font.size:=10;
          ti.TextSettings.font.style:=[Tfontstyle.fsbold];
          end;
       end;
    Jusqu'à ce que je m'aperçoive qu'une propriété HeaderSettings était apparue, avec laquelle tout cela pouvait être réglé à la conception ou par programmation.

    Je ne sais pas si c'est ce que tu cherchais ?

    EDIT : Mince je ne suis pas allé au bout du fil avant de répondre ... belle leçon à retenir

  16. #16
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2007
    Messages
    400
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 400
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    Je butte désormais sur l'ordre de tri.
    J'ai créé un dictionnaire FSortList: TDictionary<TColumn,smallint>; où le smallint serait
    1 - DESC
    0 - pas de tri
    -1 - ASC
    et je pensais utiliser l'index de la colonne dans la liste pour obtenir le numéro d'ordre, quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    numerodordre=valeurlapaire*indexdelapaire
    sauf que l'index je ne sais pas trop comment l'obtenir, une idée ?
    Peut-être dois-je utilisé autre chose une Queue une Pile ou ??
    D'accord avec anapurna.
    Peut-être un début de solution dans ce que je t'ai fait parvenir en MP ?

  17. #17
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 586
    Billets dans le blog
    65
    Par défaut
    @navyg,
    comme tu verras post #13 je suis passé à une énumération pour ce qui est du type de tri.
    pour les ajouts de version (voir #14) sur THeader c'est vrai que ça change la donne je n'en ai pas encore fait le tour.
    Quant à l'index j'ai trouvé une solution :
    1. Ma FSortList est devenu une simple TList<TColumn> il n'y a donc pas de problème d'index IndexOf(Column) me donne le bon.
    2. Le type de tri est désormais stocké dans le dictionnaire des colonnes triées dans l'objet associé.


    Avantage de cette démarche, je pense (pas essayé) que si une colonne est déplacée au runtime cela n'a aucune importance. Enfin cela en aura si j'arrive à trouver le moyen de trouver la colonne à partir du THeader !

  18. #18
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2007
    Messages
    400
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 400
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    @navyg,
    Enfin cela en aura si j'arrive à trouver le moyen de trouver la colonne à partir du THeader !
    En fait le Theader ne me semble pas relié à la colonne mais à la TstringGrid car il contient tous les items de la ligne de titres ?
    puisqu'on peut accéder à header.items[i] ?

    Je dis peut-être des bêtises mais il me semble que la propriété header de la colonne est un des items de Theader.items...

    Peut-être en passant en revue les libellés des colonnes tu obtiens l'index ?

    Tu as un exemple de ce que tu cherches à faire ?

  19. #19
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 586
    Billets dans le blog
    65
    Par défaut
    Citation Envoyé par navyg Voir le message
    Tu as un exemple de ce que tu cherches à faire ?
    Pour "simplifier" il s'agit de gérer le Onclick sur le SVG
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    procedure TFrame5.ClickSort(Sender: TObject);
    begin
      var aColumn:=Grid1.Columns[TSKSVG(Sender).tag];  // ici j'ai triché 
      ChangeColumnSort(AColumn);
      Grid1.NeedStyleLookup;
    end;
    pour l'instant je pars du postulat que la colonne ne peut être déplacée donc met un tag:=column.index à la création du SVG mais utiliser les tags je suis pas chaud surtout dans l'optique composant.

    Donc, je peux retrouver le ItemHeader comme ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ItemHeader:=TItemHeader(TSKSVG(sender).parent);
    et à l'occasion
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Header:= THeader(ItemHeader.parent)
    mais quid pour obtenir la colonne ? après recherche dans les sources
    et c'est tout bête
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      
    aHeaderItem:=THeaderItem(TSKSVG(Sender).parent);
    ChangeColumnSort(Grid1.ColumnByIndex(aHeaderItem.Index));
    du coup dans mes recherches j'ai découvert la procedure TColumn.Changed qui va remplacer avantageusement, je pense, mes Grid1.NeedStyleLookup qui me faisaient tiquer, pourquoi redessiner la grille quand on peut seulment redessiner la colonne. Cela demande expérimentations, en cours avant confirmation

  20. #20
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2007
    Messages
    400
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 400
    Par défaut
    Si tu as accès au headeritem, pour trouver le rang de la colonne tu as theaderitem.index ?

    EDIT ... encore grillé !

Discussions similaires

  1. Aligner les titres des colonnes dans un datagrid
    Par bonnet85 dans le forum VB 6 et antérieur
    Réponses: 0
    Dernier message: 02/04/2008, 16h01
  2. Probleme d'affichage dans les titres des fenetres
    Par pierrot10 dans le forum Windows XP
    Réponses: 4
    Dernier message: 24/01/2008, 09h01
  3. Affichage du titre des colonnes dans un DBGrid
    Par Debure dans le forum C++Builder
    Réponses: 6
    Dernier message: 05/10/2005, 23h41
  4. DBGrid, comment dessiner dans les titres des colonnes
    Par dleu dans le forum Bases de données
    Réponses: 9
    Dernier message: 04/11/2004, 17h49
  5. [dbGrid]Image dans le titre des colonnes d'un dbGrid
    Par dleu dans le forum Bases de données
    Réponses: 1
    Dernier message: 31/08/2004, 18h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo