{ ------------------------------------------------------------- }
{ Purpose : NextGrid 6                                          }
{ By      : Bojan Nikolic                                       }
{ For     : BergSoft                                            }
{ ------------------------------------------------------------- }
{ Copyright (C) BergSoft.net 2015. All Rights Reserved.         }
{ ------------------------------------------------------------- }
{$R Columns.res}

unit NxColumnsEditor6;

interface

uses
  { Standard }
  Classes, Types, Windows, Graphics, ImgList,
  { Standard.Design }
  DesignIntf, DesignEditors, VCLEditors,
  { Standard.Controls }
  Controls, StdCtrls, Menus, ComCtrls, ExtCtrls,
  { Next Standard 6 }
  NxConsts6, NxTypes6, NxIntf6, NxClasses6, NxStdCtrls6, NxControls6,
  { Next Standard 6 (Design) }
  NxStandardReg6, NxDesignWindow6,
  { NextGrid 6 }
  NxCustomGrid6, NxGridView6, NxColumns6, NxGrid6, NxCells6,
  { NextLayout 6 }
  NxLayoutIntf6, NxLayoutNodes6, NxLayout6, NxAssociates6, NxVirtualGrid6;

type
  TNxColumnsEditor6 = class;
  TNxEditorClass = class of TNxColumnsEditor6;

  { TNxColumnsEditor6 }

  TNxColumnsEditor6 = class(TNxDesignWindow, INxPropertyListener)
    { Form Code }
    Palette: TNxToolPalette6;
    Icons: TImageList;
    grEditor: TNextGrid6;
    gvReport: TNxReportGridView6;
    coIcon: TNxIconColumn6;
    coEditing: TNxIconColumn6;
    coColor: TNxTextColumn6;
    NxTextColumn64: TNxTextColumn6;
    NxTextColumn65: TNxTextColumn6;
    NxTextColumn66: TNxTextColumn6;
    PopupMenu1: TPopupMenu;
    Delete1: TMenuItem;
    N1: TMenuItem;
    ConvertTo: TMenuItem;
    Duplicate1: TMenuItem;
    N2: TMenuItem;
    MoveUp1: TMenuItem;
    MoveDown1: TMenuItem;
    ImageList1: TImageList;
    N3: TMenuItem;
    ShowQuickProperties1: TMenuItem;
    StatusBar1: TStatusBar;
    frProperties: TNextLayout6;
    Properties: TImageList;
    AlignmentImages: TImageList;
    ImageList2: TImageList;
    coSize: TNxIconColumn6;
    EditHeadersCaption1: TMenuItem;
    N4: TMenuItem;
    SetMisingNames1: TMenuItem;
    NxToolbar61: TNxToolbar6;
    ImageList3: TImageList;
    DisableSortingforColumn1: TMenuItem;
    procedure PaletteButtonClick(Sender: TObject; Index: Integer);
    procedure FormShow(Sender: TObject);
    procedure grEditorSelect(Sender: TObject; ACol, ARow: Integer);
    procedure Delete1Click(Sender: TObject);
    procedure MoveUp1Click(Sender: TObject);
    procedure MoveDown1Click(Sender: TObject);
    procedure grEditorCellDblClick(Sender: TObject; ACol, ARow: Integer);
    procedure ShowQuickProperties1Click(Sender: TObject);
    procedure frPropertiesSetProperty(Sender: TObject; Node: TNxLayoutNode6);
    procedure coColorDrawContent(Sender: TObject; ACol, ARow: Integer;
      CellRect: TRect; State: TNxCellPaintingState);
    procedure coSizeGetValue(Sender: TObject; ACol, ARow: Integer;
      var Value: Integer);
    procedure NxTextColumn64GetText(Sender: TObject; ACol, ARow: Integer;
      var Text: WideString);
    procedure grEditorAfterEdit(Sender: TObject; ACol, ARow: Integer;
      Text: WideString);
    procedure EditHeadersCaption1Click(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure gvReportRowMoveDrop(Sender: TObject; Row, ParentRow: INxRow; CurIndex, NewIndex: Integer);
    procedure SetMisingNames1Click(Sender: TObject);
    procedure NxToolbar61ButtonClick(Sender: TObject; const Index: Integer);
    procedure DisableSortingforColumn1Click(Sender: TObject);
    procedure PopupMenu1Popup(Sender: TObject);
  private
    function GetGrid: TNxCustomGrid6;
    function GetImageIndex(ColumnClass: TNxColumnClass): Integer;
    function GetSelected: TNxColumn6;
    function GetSelectedInstance: TObject;
  protected
    procedure AddButton(Palette: string; ComponentClass: TComponentClass;
      ImageIndex: Integer); virtual;
    procedure AddButtons; virtual;
    procedure AddIcon(Res: string);
    procedure AddRow(Row: INxCellsRow; Column: TNxColumn6);
    procedure DoButtonsEditorClick(Sender: TObject);
    procedure DoConvertMenuClick(Sender: TObject);
    procedure DoHelpButtonClick(Sender: TObject);
    procedure DoPreviewDraw(Sender: TObject; Dest: TRect);
    function GetUniqueNameSuggestion(const Index: Integer): string; virtual;
    procedure LoadColumns;
    procedure LoadIcons; virtual;
    procedure PropertyChanged(Sender: TObject);
    procedure ReadProperties;
    procedure UpdateCaptions;
    procedure UpdateRow(Index: Integer);
    procedure UpdateStatusBar;
    procedure UpdateStatusBarPanels(Index: Integer); virtual;
  public
    constructor Create(AOwner: TComponent); override;
    function CreateColumn(ColumnClass: TNxColumnClass): TNxColumn6;
    { Properties }
    property Grid: TNxCustomGrid6 read GetGrid;
    property Selected: TNxColumn6 read GetSelected;
    property SelectedInstance: TObject read GetSelectedInstance;
  end;

implementation

uses
  { Standard }
  SysUtils, Dialogs, Forms, ShellApi, Math, ColnEdit,
  { NextGrid 6 }
  NxColumnViewClasses6;

{$R *.dfm}

procedure TNxColumnsEditor6.AddButton(Palette: string;
  ComponentClass: TComponentClass; ImageIndex: Integer);
var
  MenuItem: TMenuItem;
begin
  with Self.Palette.Add(Palette, ComponentClass, ImageIndex) do
  begin
    ShowHint := True;
    Hint := ComponentClass.ClassName;

    { Populate "Convert To" }
    MenuItem := TMenuItem.Create(ConvertTo);
    MenuItem.Caption := ComponentClass.ClassName;
    MenuItem.OnClick := DoConvertMenuClick;
    MenuItem.ImageIndex := ImageIndex;

    ConvertTo.Add(MenuItem);
  end;
end;

procedure TNxColumnsEditor6.AddButtons;
begin
  AddButton('Standard', TNxTextColumn6, 0);
  AddButton('Standard', TNxNumberColumn6, 1);
  AddButton('Standard', TNxCheckBoxColumn6, 2);
  AddButton('Standard', TNxComboBoxColumn6, 3);
  AddButton('Standard', TNxListColumn6, 4);
  AddButton('Standard', TNxIconColumn6, 5);
  AddButton('Standard', TNxDateColumn6, 6);
  AddButton('Standard', TNxTimeColumn6, 7);
  AddButton('Standard', TNxMemoColumn6, 8);
  AddButton('Standard', TNxIncrementColumn6, 9);
  AddButton('Standard', TNxButtonColumn6, 10);
  AddButton('Standard', TNxToolbarColumn6, 11);

  AddButton('Additional', TNxColorColumn6, 12);
  AddButton('Additional', TNxTrackbarColumn6, 13);
  AddButton('Additional', TNxProgressColumn6, 14);
  AddButton('Additional', TNxGraphicColumn6, 15);
  AddButton('Additional', TNxHTMLColumn6, 16);
  AddButton('Additional', TNxCheckComboBoxColumn6, 17);
  AddButton('Additional', TNxRateColumn6, 18);
  AddButton('Additional', TNxTreeColumn6, 19);
end;

procedure TNxColumnsEditor6.AddIcon(Res: string);
var
  Bitmap: TBitmap;
begin
  Bitmap := TBitmap.Create;

  try
    Bitmap.LoadFromResourceName(HInstance, Res);

    { Add to list }
    Icons.AddMasked(Bitmap, Bitmap.Canvas.Pixels[0, Bitmap.Height - 1]);
  finally

  end;
end;

procedure TNxColumnsEditor6.AddRow(Row: INxCellsRow; Column: TNxColumn6);
begin
  with Row.Cells do
  begin
    Item[0].AsInteger := GetImageIndex(TNxColumnClass(Column.ClassType));
    Item[1].AsBoolean := not Column.Editing;
    Item[4].AsString := Column.Header.Caption;
    Item[5].AsString := Column.Name;
    Item[6].AsString := Column.ClassName;
  end;

  Column.PropertyNotification(Self);
end;

constructor TNxColumnsEditor6.Create(AOwner: TComponent);
begin
  inherited;
  { Icons }
  LoadIcons;

  { Palette }
  AddButtons;

  { Hide Quick properties }
  frProperties.Hide;
  ClientWidth := ClientWidth - frProperties.Width;

  grEditor.SelectionColor := $00ffe8cc;
  grEditor.SelectionTextColor := clWindowText;
end;

function TNxColumnsEditor6.CreateColumn(ColumnClass: TNxColumnClass): TNxColumn6;
var
  NewName: TComponentName;
begin
  Result := ColumnClass.Create(Grid.Owner);

  { Set Unique Name to View }
  NewName := Designer.UniqueName(Result.ClassName);

  Result.Name := NewName;

  { Add Object into List }
  Grid.Columns.Add(Result);

  { Editor }
  AddRow(grEditor.AddRow, Result);

  grEditor.SelectedRow := grEditor.LastAddedRow;

  UpdateStatusBar;
    
  { Enable Save Btn. }
  Designer.Modified;
end;

procedure TNxColumnsEditor6.Delete1Click(Sender: TObject);
var
  Index: Integer;
begin
  { Note: DeleteRow auto shift selection }
  Index := grEditor.SelectedRow;

  if grEditor.RowExists(Index) then
  begin
    Designer.NoSelection;

    { Destroy & delete }
    Grid.Columns[Index].Free;

    { Delete in editor }
    grEditor.DeleteRow(Index);

    { Enable Save Btn. }
    Designer.Modified;

    UpdateStatusBar;
  end;
end;

procedure TNxColumnsEditor6.DisableSortingforColumn1Click(Sender: TObject);
begin
  if Assigned(Selected) then
  begin
    Selected.SortType := stNone;
  end;
end;

procedure TNxColumnsEditor6.DoConvertMenuClick(Sender: TObject);
var
  Column: TNxColumn6;
  ColumnClass: TNxColumnClass;
  ColumnName: string;
  NewCaption: string;
  Index, Position: Integer;
begin
  NewCaption := TMenuItem(Sender).Caption;

  if MessageDlg('Convert to ' + NewCaption + '?', mtConfirmation,
    [mbYes, mbNo], 0) = mrYes then
  begin

    if Assigned(Selected) then
    begin
      Designer.ClearSelection;

      ColumnName := Selected.Name;
      Position := Selected.Position;
      Index := Selected.Index;
      ColumnClass := TNxColumnClass(GetClass(NewCaption));

      { Create & copy old }
      Column := ColumnClass.Create(Grid.Owner);

      Column.Assign(Selected);

      { Destroy old }
      Grid.Columns[grEditor.SelectedRow].Free;

      { Insert new }
      Grid.Columns.Insert(Index, Column);

      Column.Name := ColumnName;
      Column.Position := Position;

      UpdateRow(Index);

      { Designer }
      Designer.SelectComponent(Column);
      Designer.Modified;

      UpdateStatusBar;
    end;

  end;
end;

procedure TNxColumnsEditor6.DoHelpButtonClick(Sender: TObject);
begin
  ShellExecute(0, 'open', 'http://dn.bergsoft.net/numeric-formatmask.htm', '', '', SW_SHOWNORMAL);
end;

procedure TNxColumnsEditor6.DoPreviewDraw(Sender: TObject; Dest: TRect);
var
  PreviewCell: INxCell;
  RowView: INxRowView;
  R: TRect;
begin
  if Assigned(Selected) then
    with Selected.View do
    begin
      Canvas := frProperties.Canvas;
      Canvas.Brush.Color := ColorOf(seWindowFrame);
      Canvas.FrameRect(Dest);
      R := Dest;
      InflateRect(R, -1, -1);
      ClientRect := R;
      try
        PreviewCell := CreateCell(Self.Selected.DataType);
        Cell := PreviewCell;
        PreviewCell.AsString := Self.Selected.PlaceholderText;
        PreviewCell.Color := Self.Selected.Color;
        Canvas := frProperties.Canvas;

        Style := Grid.StylePaint;
        Style.Canvas := frProperties.Canvas;
        Control := frProperties;

        DrawingOptions := Self.Selected.DrawingOptions;

        if Supports(Self.Selected.View, INxRowView, RowView) then
        begin
          RowView.Row := nil;
        end;

        try
          Paint;
        except
          on E : Exception do
          begin
{$IFDEF LOG_FILE}

{$ENDIF}
            frProperties.Canvas.Brush.Color := clRed;
            frProperties.Canvas.FillRect(Dest);
          end;
        end;
      finally
        PreviewCell := nil;
        Cell := nil;
      end;
    end;
end;

procedure TNxColumnsEditor6.EditHeadersCaption1Click(Sender: TObject);
begin
  if Assigned(Selected) then
  begin
    grEditor.EditCell(NxTextColumn64.Index, grEditor.SelectedRow, '', True);
  end;
end;

procedure TNxColumnsEditor6.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if Key = VK_ESCAPE then Close;
end;

procedure TNxColumnsEditor6.FormShow(Sender: TObject);
begin
  Caption := 'Columns Editor - ' + Grid.Name;
  LoadColumns;
  ActiveControl := grEditor;
end;

procedure TNxColumnsEditor6.frPropertiesSetProperty(Sender: TObject;
  Node: TNxLayoutNode6);
begin
  if Node.BindProperty = 'Visible'
    then UpdateStatusBar;
    
  Designer.Modified;
end;

function TNxColumnsEditor6.GetGrid: TNxCustomGrid6;
begin
  Result := TNxCustomGrid6(OwnerControl);
end;

function TNxColumnsEditor6.GetImageIndex(ColumnClass: TNxColumnClass): Integer;
var
  i, j: Integer;
  Button: TNxPaletteButton;
begin
  { Default }
  Result := -1;

  for i := 0 to Pred(Palette.Count) do
    for j := 0 to Pred(Palette.Palette[i].Count) do
    begin
      Button := Palette.Palette[i].Button[j];

      if Assigned(Button) then
      begin
        if Button.ReferenceType = ColumnClass then
        begin
          Result := Button.ImageIndex;
          Exit;
        end;
      end;
    end;
end;

function TNxColumnsEditor6.GetSelected: TNxColumn6;
begin
  Result := nil;

  if Grid.Columns.Exist(grEditor.SelectedRow)
    then Result := Grid.Columns[grEditor.SelectedRow];
end;

function TNxColumnsEditor6.GetSelectedInstance: TObject;
var
  Ref: IInterfaceComponentReference;
begin
  Result := nil;
  if Supports(Selected, IInterfaceComponentReference, Ref) then
  begin
    Result := Ref.GetComponent;
  end;
end;

function TNxColumnsEditor6.GetUniqueNameSuggestion(const Index: Integer): string;
begin
  Result := Designer.UniqueName(Grid.Columns[Index].ClassName);
end;

procedure TNxColumnsEditor6.grEditorAfterEdit(Sender: TObject; ACol,
  ARow: Integer; Text: WideString);
begin
  Grid.Columns[ARow].Header.Caption := Text;
  Designer.Modified;
end;

procedure TNxColumnsEditor6.grEditorCellDblClick(Sender: TObject; ACol,
  ARow: Integer);
begin
  if ACol = 1 then
  begin
    Grid.Columns[ARow].Editing := not Grid.Columns[ARow].Editing;
    grEditor.Cell[ACol, ARow].AsBoolean := not Grid.Columns[ARow].Editing;

    Designer.Modified;
  end;
  if ACol = NxTextColumn64.Index then
  begin
    grEditor.EditCell(ACol, ARow, '', True);
  end;
end;

procedure TNxColumnsEditor6.grEditorSelect(Sender: TObject; ACol,
  ARow: Integer);
begin
  if grEditor.RowExists(ARow) then
  begin
    Designer.SelectComponent(Grid.Columns[ARow]);

    UpdateStatusBarPanels(ARow);

    if frProperties.Visible
      then ReadProperties;
  end;
end;

procedure TNxColumnsEditor6.gvReportRowMoveDrop(Sender: TObject; Row, ParentRow: INxRow;
  CurIndex, NewIndex: Integer);
var
  Column: TNxColumn6;
begin
  Column := Grid.Columns[CurIndex];
  Grid.Columns.Move(CurIndex, NewIndex);
  Column.Position := NewIndex;
  gvReport.RefreshColumn(NxTextColumn64, gaBody);
end;

procedure TNxColumnsEditor6.LoadColumns;
var
  i: Integer;
begin
  grEditor.ClearRows;

  for i := 0 to Pred(Grid.Columns.Count) do
  begin
    AddRow(grEditor.AddRow, Grid.Columns[i]);
  end;

  UpdateStatusBar;
end;

procedure TNxColumnsEditor6.LoadIcons;
begin
  AddIcon('TEXTCOLUMN');
  AddIcon('NUMBERCOLUMN');
  AddIcon('CHECKBOXCOLUMN');
  AddIcon('COMBOBOXCOLUMN');
  AddIcon('LISTCOLUMN');
  AddIcon('ICONCOLUMN');
  AddIcon('DATECOLUMN');
  AddIcon('TIMECOLUMN');
  AddIcon('MEMOCOLUMN');
  AddIcon('INCREMENTCOLUMN');
  AddIcon('BUTTONCOLUMN');
  AddIcon('TOOLBARCOLUMN');

  AddIcon('COLORCOLUMN');
  AddIcon('TRACKBARCOLUMN');
  AddIcon('PROGRESSCOLUMN');
  AddIcon('GRAPHICCOLUMN');
  AddIcon('HTMLCOLUMN');
  AddIcon('CHECKCOMBOBOXCOLUMN');
  AddIcon('RATECOLUMN');

  AddIcon('TREECOLUMN');

  AddIcon('LOOKUPCOLUMN');
end;

procedure TNxColumnsEditor6.MoveDown1Click(Sender: TObject);
var
  FromPos, ToPos: Integer;
begin
  FromPos := grEditor.SelectedRow;
  ToPos := Succ(FromPos);

  if Grid.Columns.Exist(ToPos) then
  begin
    { Index }
    Grid.Columns.Move(FromPos, ToPos);

    { Position }
    Grid.Columns[ToPos].Position := ToPos;

    grEditor.MoveRow(FromPos, ToPos);
    grEditor.MoveByRow(1);

    { Enable Save Btn. }
    Designer.Modified;

    UpdateCaptions;
  end
  else Beep;
end;

procedure TNxColumnsEditor6.MoveUp1Click(Sender: TObject);
var
  FromPos, ToPos: Integer;
begin
  FromPos := grEditor.SelectedRow;
  ToPos := Pred(FromPos);

  if Grid.Columns.Exist(ToPos) then
  begin
    { Index }
    Grid.Columns.Move(FromPos, ToPos);

    { Position }
    Grid.Columns[ToPos].Position := ToPos;

    grEditor.MoveRow(FromPos, ToPos);
    grEditor.MoveByRow(-1);

    { Enable Save Btn. }
    Designer.Modified;

    UpdateCaptions;

  end else Beep;
end;

procedure TNxColumnsEditor6.NxTextColumn64GetText(Sender: TObject; ACol,
  ARow: Integer; var Text: WideString);
begin
  Text := IntToStr(ARow) + ': ' + Text;
end;

procedure TNxColumnsEditor6.NxToolbar61ButtonClick(Sender: TObject; const Index: Integer);
var
  i: Integer;
begin
  { Delete }
  if Index = 0 then
  begin
    Delete1Click(Delete1);
  end;

  { Clear }
  if Index = 1 then
    if MessageDlg('Are you sure?', mtConfirmation, [mbYes, mbNo], 0) = mrYes then
    begin
      Designer.NoSelection;

      { Destroy & delete all }
      for i := Pred(Grid.Columns.Count) downto 0
        do Grid.Columns[i].Free;

      { Delete in editor }
      grEditor.ClearRows;

      { Enable Save Btn. }
      Designer.Modified;

      UpdateStatusBar;
    end;

  if Index = 3 then
    MoveUp1Click(MoveUp1);

  if Index = 4 then
    MoveDown1Click(MoveDown1);

end;

procedure TNxColumnsEditor6.coColorDrawContent(Sender: TObject; ACol,
  ARow: Integer; CellRect: TRect; State: TNxCellPaintingState);
begin
  with grEditor.Canvas do
  begin
    if Grid.Columns.Exist(ARow) then
      if Grid.Columns[ARow].Color <> Grid.Color then
      begin
        Pen.Color := clSilver;
        Brush.Color := Grid.Columns[ARow].Color;
        FillRect(CellRect);
      end;
  end;
end;

procedure TNxColumnsEditor6.coSizeGetValue(Sender: TObject; ACol, ARow: Integer;
  var Value: Integer);
begin
  Value := -1;               
  if Grid.Columns[ARow].AutoSize then Value := 0;
  if not Grid.Columns[ARow].Resizeable then Value := 1;
end;

procedure TNxColumnsEditor6.PaletteButtonClick(Sender: TObject; Index: Integer);
begin
  CreateColumn(TNxColumnClass(Palette.Palette[Palette.ItemIndex].Button[Index].ReferenceType));
end;

procedure TNxColumnsEditor6.PopupMenu1Popup(Sender: TObject);
begin
  DisableSortingforColumn1.Enabled := Selected.SortType <> stNone;
end;

procedure TNxColumnsEditor6.PropertyChanged(Sender: TObject);
begin
  if Sender is TNxColumn6 then
  begin
    grEditor.RefreshRow(TNxColumn6(Sender).Index);
    UpdateRow(TNxColumn6(Sender).Index);
  end;
end;

procedure TNxColumnsEditor6.ReadProperties;
begin
  if Selected = nil then Exit;

  { Assign previous editing }
  frProperties.EndEditing;

  frProperties.ActiveNode := nil;

  { Erase first }
  frProperties.Nodes.Clear;

  frProperties.Associates.Clear;

  frProperties.Associates.Add(TPersistent(SelectedInstance));

  { Add root }
  with frProperties.Nodes.Add(TNxLabelLayoutNode6) do
  begin
    TextBefore := 'Properties';
    Padding.Left := 16;
    Padding.Top := 4;

    with ChildNodes.Add(TNxLabelLayoutNode6) do
    begin
      TextBefore := 'Common';
      Width := 80;
      Padding.Bottom := 8;
      ExpandLock := True;

      with ChildNodes.Add(TNxLabelLayoutNode6) as TNxLabelLayoutNode6 do
      begin
        TextBeforeWidth := 60;
        Width := TextBeforeWidth + Selected.Width + pdStandard;
        Height := Grid.RowHeight + pdStandard;
        Hint := 'Preview' + #13#10 + IntToStr(Selected.Width) + ' x ' + IntToStr(Grid.RowHeight);
        Clearing := [clRight];
        OnCustomDrawContent := DoPreviewDraw;
      end;

      with ChildNodes.Add(TNxEditLayoutNode6) do
      begin
        BindProperty := 'Name';
        TextBefore := 'Name';
        TextBeforeWidth := 60;
        Width := 180;
        Clearing := [clRight];
      end;

      with ChildNodes.Add(TNxCheckBoxLayoutNode6) as TNxCheckBoxLayoutNode6 do
      begin
        Button := True;
        ButtonImageIndex := 0;
        BindProperty := 'Enabled';
        TextBefore := '';
        TextBeforeWidth := 60;
        Hint := 'Enabled';
        Margins.SetBounds(0, 0, 0, pdDouble);
      end;

      with ChildNodes.Add(TNxCheckBoxLayoutNode6) as TNxCheckBoxLayoutNode6 do
      begin
        Button := True;
        ButtonImageIndex := 1;
        BindProperty := 'Visible';
        Hint := 'Visible';
        Margins.SetBounds(0, 0, 0, pdDouble);
      end;

      with ChildNodes.Add(TNxCheckBoxLayoutNode6) as TNxCheckBoxLayoutNode6 do
      begin
        Button := True;
        BindProperty := 'Editing';
        ButtonImageIndex := 2;
        Hint := 'Editing';
        Margins.SetBounds(0, 0, 0, pdDouble);
      end;

      with ChildNodes.Add(TNxCheckBoxLayoutNode6) as TNxCheckBoxLayoutNode6 do
      begin
        Button := True;
        BindProperty := 'Inserting';
        ButtonImageIndex := 3;
        Hint := 'Inserting';
        Margins.SetBounds(0, 0, 0, pdDouble);
      end;

      with ChildNodes.Add(TNxCheckBoxLayoutNode6) as TNxCheckBoxLayoutNode6 do
      begin
        Button := True;
        ButtonImageIndex := 4;
        BindProperty := 'Resizeable';
        Hint := 'Resizeable';
        Clearing := [clRight];
        Margins.SetBounds(0, 0, 0, pdDouble);
      end;

      with ChildNodes.Add(TNxToolbarLayoutNode6) as TNxToolbarLayoutNode6 do
      begin
        AllowAlUp := False;
        Grouped := True;
        TextBefore := 'Align';
        TextBeforeWidth := 60;
        BindProperty := 'Alignment';
        Width := 160;
        Images := AlignmentImages;
        with Buttons do
        begin
          with Add as TNxToolbarNodeButton do
          begin
            BindValue := 'taLeftJustify';
            Hint := 'Left (taLeftJustify)';
            ImageIndex := 0;
          end;
          with Add as TNxToolbarNodeButton do
          begin
            BindValue := 'taCenter';
            Hint := 'Center (taCenter)';
            ImageIndex := 1;
          end;
          with Add as TNxToolbarNodeButton do
          begin
            BindValue := 'taRightJustify';
            Hint := 'Right (taRightJustify)';
            ImageIndex := 2;
          end;
        end;
      end;

      with ChildNodes.Add(TNxSpinLayoutNode6) as TNxSpinLayoutNode6 do
      begin
        BindProperty := 'Width';
        Min := 8;
        Max := MaxInt;
        Precision := 0;
        TextBefore := 'Width';
        TextBeforeWidth := 60;
        TextAfter := 'pt';
        ClientWidth := 60;
      end;

    end;

    with ChildNodes.Add(TNxLabelLayoutNode6) do
    begin
      Padding.Bottom := 8;
      TextBefore := 'Header';
      Width := 80;
      ExpandLock := True;

      with ChildNodes.Add(TNxEditLayoutNode6) as TNxEditLayoutNode6 do
      begin
        TextBefore := 'Caption';
        TextBeforeWidth := 60;
        BindProperty := 'Header.Caption';
        Width := 160;
      end;

      with ChildNodes.Add(TNxCheckBoxLayoutNode6) as TNxCheckBoxLayoutNode6 do
      begin
        Button := True;
        ButtonImageIndex := 5;
        BindProperty := 'Header.Multiline';
        Hint := 'Multiline';
        Clearing := [clRight];
      end;

      with ChildNodes.Add(TNxToolbarLayoutNode6) as TNxToolbarLayoutNode6 do
      begin
        AllowAlUp := False;
        Grouped := True;
        TextBefore := 'Align';
        TextBeforeWidth := 60;
        BindProperty := 'Header.Alignment';
        Width := 160;
        Images := AlignmentImages;
        with Buttons do
        begin
          with Add as TNxToolbarNodeButton do
          begin
            BindValue := 'taLeftJustify';
            Hint := 'Left (taLeftJustify)';
            ImageIndex := 0;
          end;
          with Add as TNxToolbarNodeButton do
          begin
            BindValue := 'taCenter';
            Hint := 'Center (taCenter)';
            ImageIndex := 1;
          end;
          with Add as TNxToolbarNodeButton do
          begin
            BindValue := 'taRightJustify';
            Hint := 'Right (taRightJustify)';
            ImageIndex := 2;
          end;
        end;
      end;

    end;

    with ChildNodes.Add(TNxLabelLayoutNode6) do
    begin
      Padding.Bottom := 8;
      TextBefore := 'Footer';
      Width := 80;
      ExpandLock := True;

      with ChildNodes.Add(TNxEditLayoutNode6) as TNxEditLayoutNode6 do
      begin
        BindProperty := 'Footer.Caption';
        TextBefore := 'Caption';
        TextBeforeAlignment := taRightJustify;
        TextBeforeWidth := 60;
        Clearing := [clRight];
        Width := 160;
      end;

      with ChildNodes.Add(TNxEditLayoutNode6) as TNxEditLayoutNode6 do
      begin
        BindProperty := 'Footer.FormatMask';
        TextBefore := 'Mask';
        TextBeforeWidth := 60;
        Clearing := [clRight];
        ClientWidth := 80;
      end;

      with ChildNodes.Add(TNxToolbarLayoutNode6) as TNxToolbarLayoutNode6 do
      begin
        AllowAlUp := False;
        Grouped := True;
        TextBefore := 'Formula';
        TextBeforeWidth := 60;
        BindProperty := 'Footer.FormulaKind';
        Images := Properties;
        with Buttons do
        begin
          with Add as TNxToolbarNodeButton do
          begin
            BindValue := 'fkNone';
            Hint := 'None (fkNone)';
            ImageIndex := 7;
          end;
          with Add as TNxToolbarNodeButton do
          begin
            BindValue := 'fkAverage';
            Hint := 'Average (fkAverage)';
            Text := 'AVG';
          end;
          with Add as TNxToolbarNodeButton do
          begin
            BindValue := 'fkCount';
            Hint := 'Count (fkCount)';
            Text := 'COUNT';
          end;
          with Add as TNxToolbarNodeButton do
          begin
            BindValue := 'fkSum';
            Hint := 'Sum (fkSum)';
            Text := 'SUM';
          end;
        end;
      end;
    end;

    { TNxToolbarColumn6 }

    if SelectedInstance is TNxToolbarColumn6 then
    begin

      with ChildNodes.Add(TNxLabelLayoutNode6) do
      begin
        Padding.Bottom := 8;
        TextBefore := 'Toolbar';
        Width := 80;
        ExpandLock := True;

        with ChildNodes.Add(TNxButtonLayoutNode6) as TNxButtonLayoutNode6 do
        begin
          Value := 'Buttons...';
          ClientWidth := 65;
          OnButtonClick := DoButtonsEditorClick;
        end;
      end;

    end;

    if SelectedInstance is TNxIconColumn6 then
    begin

      with ChildNodes.Add(TNxLabelLayoutNode6) do
      begin
        Padding.Bottom := 8;
        TextBefore := 'Interaction';
        Width := 80;
        ExpandLock := True;

        with ChildNodes.Add(TNxCheckBoxLayoutNode6) do
        begin
          TextBefore := 'Button';
          TextBeforeWidth := 60;
          BindProperty := 'Button';
          Clearing := [clRight];
        end;

        with ChildNodes.Add(TNxCheckBoxLayoutNode6) do
        begin
          BindProperty := 'CycleImages';
          TextBefore := 'Cycle';
          TextBeforeWidth := 60;
          Hint := 'This property require Button property to be set to True.';
        end;

      end;
    end;

    { TNxNumberColumn6 }

    if SelectedInstance is TNxNumberColumn6 then
    begin

      with ChildNodes.Add(TNxLabelLayoutNode6) do
      begin
        Padding.Bottom := 8;
        TextBefore := 'Number';
        Width := 80;
        ExpandLock := True;

        with ChildNodes.Add(TNxSpinLayoutNode6) as TNxSpinLayoutNode6 do
        begin
          BindProperty := 'Min';
          Precision := 0;
          TextBefore := 'Range';
          TextBeforeWidth := 60;
          ClientWidth := 40;
        end;

        with ChildNodes.Add(TNxSpinLayoutNode6) as TNxSpinLayoutNode6 do
        begin
          BindProperty := 'Max';
          Precision := 0;
          TextBefore := '-';
          TextBeforeAlignment := taLeftJustify;
          TextBeforeWidth := 4;
          Clearing := [clRight];
          ClientWidth := 40;
        end;

        with ChildNodes.Add(TNxSpinLayoutNode6) as TNxSpinLayoutNode6 do
        begin
          BindProperty := 'Precision';
          Precision := 0;
          TextBefore := 'Prec.';
          TextBeforeWidth := 60;
          Clearing := [clRight];
          ClientWidth := 40;
        end;

        with ChildNodes.Add(TNxEditLayoutNode6) as TNxEditLayoutNode6 do
        begin
          BindProperty := 'FormatMask';
          TextBefore := 'Mask';
          TextBeforeWidth := 60;
          IconIndexAfter := 6;
          OnImageAfterClick := DoHelpButtonClick;
          VisibleEntities := [enTextBefore, enContent, enIconAfter];
          ClientWidth := 80;
        end;

        if SelectedInstance is TNxProgressColumn6 then
        begin

          with ChildNodes.Add(TNxSpinLayoutNode6) as TNxSpinLayoutNode6 do
          begin
            BindProperty := 'TextWidth';
            Precision := 0;
            TextBefore := 'TextWidth';
            TextBeforeWidth := 60;
            Clearing := [clRight];
            ClientWidth := 60;
          end;

        end;

      end;

    end;

    { TNxCheckBoxColumn6 }

    if SelectedInstance is TNxCheckBoxColumn6 then
    begin
      with ChildNodes.Add(TNxLabelLayoutNode6) do
      begin
        Padding.Bottom := 8;
        TextBefore := 'CheckBox';
        Width := 80;
        ExpandLock := True;

        with ChildNodes.Add(TNxCheckBoxLayoutNode6) as TNxCheckBoxLayoutNode6 do
        begin
          TextBefore := 'ShowText';
          TextBeforeWidth := 60;
          BindProperty := 'ShowText';
          Hint := 'ShowText';
          Clearing := [clRight];
        end;
      end;
    end;

    { TNxTreeColumn6 }

    if SelectedInstance is TNxTreeColumn6 then
    begin
      with ChildNodes.Add(TNxLabelLayoutNode6) do
      begin
        Padding.Bottom := 8;
        TextBefore := 'Tree';
        Width := 80;
        ExpandLock := True;

        with ChildNodes.Add(TNxCheckBoxLayoutNode6) as TNxCheckBoxLayoutNode6 do
        begin
          TextBefore := 'ShowLines';
          TextBeforeWidth := 60;
          BindProperty := 'ShowLines';
          Hint := 'ShowLines';
          Clearing := [clRight];
        end;
      end;
    end;
  end;

  frProperties.Invalidate;
  frProperties.ReadProperties(nil);
end;

procedure TNxColumnsEditor6.SetMisingNames1Click(Sender: TObject);
var
  i: Integer;
begin
  for i := 0 to Pred(Grid.ColCount) do
  begin
    if Grid.Columns[i].Name = '' then
    begin
      { Descendants override }
      Grid.Columns[i].Name := GetUniqueNameSuggestion(i);

      { Required }
      Designer.Modified;
    end;
  end;
end;

procedure TNxColumnsEditor6.UpdateStatusBarPanels(Index: Integer);
var
  S: string;
begin
  StatusBar1.Panels[1].Text := 'Position: ' + IntToStr(Grid.Columns[Index].Position);

  StatusBar1.Panels[2].Text := '';
  if Grid.Columns[Index].Editing then StatusBar1.Panels[2].Text := 'Editable';

  if not Grid.Columns[Index].Resizeable then
    S := 'Fixed-size'
  else if Grid.Columns[Index].AutoSize then
    S := 'Auto-sized'
  else S := '';

  if (StatusBar1.Panels[2].Text <> '') and (S <> '')
    then StatusBar1.Panels[2].Text := StatusBar1.Panels[2].Text + ', ';

  StatusBar1.Panels[2].Text := StatusBar1.Panels[2].Text + S;
end;

procedure TNxColumnsEditor6.ShowQuickProperties1Click(Sender: TObject);
begin
  if not frProperties.Visible
  then
    ClientWidth := ClientWidth + frProperties.Width
  else
    ClientWidth := ClientWidth - frProperties.Width;

  frProperties.Visible := not frProperties.Visible;

  if frProperties.Visible
    then ReadProperties;
end;

procedure TNxColumnsEditor6.UpdateCaptions;
var
  i: Integer;
begin
  for i := 0 to Pred(grEditor.RowCount) do
  begin
    grEditor.Cell[3, i].AsString := IntToStr(i) + ': ' + Grid.Columns[i].Header.Caption;
  end;
end;

procedure TNxColumnsEditor6.UpdateRow(Index: Integer);
var
  Column: TNxColumn6;
begin
  if Assigned(Selected) then
    with INxCellsRow(grEditor.Row[Index]).Cells do
    begin
      Column := Grid.Columns[Index];
      Item[0].AsInteger := GetImageIndex(TNxColumnClass(Column.ClassType));
      Item[4].AsString := Column.Header.Caption;
      Item[5].AsString := Column.Name;
      Item[6].AsString := Column.ClassName;
    end;
end;

procedure TNxColumnsEditor6.UpdateStatusBar;
var
  S: string;
begin
  with Grid.Columns do
  begin
    S := 'Count: ' + IntToStr(Grid.Columns.Count);
    if Count <> VisibleCount
      then S := S + ' (' + IntToStr(Grid.Columns.VisibleCount) + ' visible)';
    StatusBar1.Panels[0].Text := S;
  end;
end;

procedure TNxColumnsEditor6.DoButtonsEditorClick(Sender: TObject);
begin
  ShowCollectionEditor(Designer, Selected, TNxToolbarColumn6(Selected).Items, 'Items');
end;

end.
