Enable multi row selection in table editor's column list. Relevant functions adjusted:

* Add to index
* Create index
* Remove Column(s) (=> makes the "Clear columns" button superfluous)
This commit is contained in:
Ansgar Becker
2009-07-26 19:45:02 +00:00
parent 00cbfa7a08
commit 4d9d5a1ff7
3 changed files with 70 additions and 96 deletions

View File

@ -2217,32 +2217,22 @@ end;
} }
function GetVTCaptions( VT: TVirtualStringTree; OnlySelected: Boolean = False; Column: Integer = 0; OnlyNodeType: TListNodeType = lntNone ): TWideStringList; function GetVTCaptions( VT: TVirtualStringTree; OnlySelected: Boolean = False; Column: Integer = 0; OnlyNodeType: TListNodeType = lntNone ): TWideStringList;
var var
SelectedNodes : TNodeArray; Node: PVirtualNode;
NodeData: PVTreeData; NodeData: PVTreeData;
i: Integer;
a : TVTreeDataArray;
begin begin
Result := TWideStringList.Create; Result := TWideStringList.Create;
if OnlySelected then if OnlySelected then Node := VT.GetFirstSelected
begin else Node := VT.GetFirst;
// Fetch only selected nodes while Assigned(Node) do begin
SelectedNodes := VT.GetSortedSelection(False); if OnlyNodeType = lntNone then // Add all nodes, regardless of their types
for i := 0 to Length(SelectedNodes) - 1 do Result.Add( VT.Text[Node, Column] )
begin
NodeData := VT.GetNodeData( SelectedNodes[i] );
if (OnlyNodeType = lntNone) // Add all nodes, regardless of their types
or (NodeData.NodeType = OnlyNodeType) then // Node in loop is of specified type
Result.Add( NodeData.Captions[Column] );
end;
end
else begin else begin
// Fetch all nodes NodeData := VT.GetNodeData(Node);
a := Mainform.GetVTreeDataArray( VT )^; if (NodeData.NodeType = OnlyNodeType) then // Node in loop is of specified type
for i := 0 to High(a) do begin Result.Add(NodeData.Captions[Column]);
if (OnlyNodeType = lntNone)
or (a[i].NodeType = OnlyNodeType) then
Result.Add( a[i].Captions[ Column ] );
end; end;
if OnlySelected then Node := VT.GetNextSelected(Node)
else Node := VT.GetNext(Node);
end; end;
end; end;

View File

@ -80,8 +80,8 @@ object frmTableEditor: TfrmTableEditor
PopupMenu = popupColumns PopupMenu = popupColumns
TabOrder = 2 TabOrder = 2
TreeOptions.MiscOptions = [toAcceptOLEDrop, toCheckSupport, toEditable, toFullRepaintOnResize, toGridExtensions, toInitOnSave, toToggleOnDblClick, toWheelPanning, toFullRowDrag, toEditOnClick] TreeOptions.MiscOptions = [toAcceptOLEDrop, toCheckSupport, toEditable, toFullRepaintOnResize, toGridExtensions, toInitOnSave, toToggleOnDblClick, toWheelPanning, toFullRowDrag, toEditOnClick]
TreeOptions.PaintOptions = [toHideFocusRect, toHotTrack, toShowDropmark, toShowHorzGridLines, toShowVertGridLines, toThemeAware, toUseBlendedImages, toUseExplorerTheme, toHideTreeLinesIfThemed] TreeOptions.PaintOptions = [toHotTrack, toShowDropmark, toShowHorzGridLines, toShowVertGridLines, toThemeAware, toUseBlendedImages, toUseExplorerTheme, toHideTreeLinesIfThemed]
TreeOptions.SelectionOptions = [toExtendedFocus, toFullRowSelect, toRightClickSelect] TreeOptions.SelectionOptions = [toExtendedFocus, toFullRowSelect, toMultiSelect, toRightClickSelect]
WantTabs = True WantTabs = True
OnAfterCellPaint = listColumnsAfterCellPaint OnAfterCellPaint = listColumnsAfterCellPaint
OnBeforeCellPaint = listColumnsBeforeCellPaint OnBeforeCellPaint = listColumnsBeforeCellPaint
@ -606,16 +606,8 @@ object frmTableEditor: TfrmTableEditor
ImageIndex = 46 ImageIndex = 46
OnClick = btnRemoveColumnClick OnClick = btnRemoveColumnClick
end end
object btnClearColumns: TToolButton
Left = 132
Top = 0
Hint = 'Remove all columns'
Caption = 'Clear'
ImageIndex = 26
OnClick = btnClearColumnsClick
end
object btnMoveUpColumn: TToolButton object btnMoveUpColumn: TToolButton
Left = 198 Left = 132
Top = 0 Top = 0
Hint = 'Move up' Hint = 'Move up'
Caption = 'Up' Caption = 'Up'
@ -623,7 +615,7 @@ object frmTableEditor: TfrmTableEditor
OnClick = btnMoveUpColumnClick OnClick = btnMoveUpColumnClick
end end
object btnMoveDownColumn: TToolButton object btnMoveDownColumn: TToolButton
Left = 264 Left = 198
Top = 0 Top = 0
Hint = 'Move down' Hint = 'Move down'
Caption = 'Down' Caption = 'Down'
@ -690,12 +682,6 @@ object frmTableEditor: TfrmTableEditor
ShortCut = 16430 ShortCut = 16430
OnClick = btnRemoveColumnClick OnClick = btnRemoveColumnClick
end end
object menuClearColumns: TMenuItem
Caption = 'Clear all columns'
ImageIndex = 26
ShortCut = 24622
OnClick = btnClearColumnsClick
end
object menuMoveUpColumn: TMenuItem object menuMoveUpColumn: TMenuItem
Caption = 'Move up' Caption = 'Move up'
ImageIndex = 74 ImageIndex = 74

View File

@ -50,7 +50,6 @@ type
tlbColumns: TToolBar; tlbColumns: TToolBar;
btnAddColumn: TToolButton; btnAddColumn: TToolButton;
btnRemoveColumn: TToolButton; btnRemoveColumn: TToolButton;
btnClearColumns: TToolButton;
btnMoveUpColumn: TToolButton; btnMoveUpColumn: TToolButton;
btnMoveDownColumn: TToolButton; btnMoveDownColumn: TToolButton;
SplitterTopBottom: TSplitter; SplitterTopBottom: TSplitter;
@ -68,7 +67,6 @@ type
popupColumns: TPopupMenu; popupColumns: TPopupMenu;
menuAddColumn: TMenuItem; menuAddColumn: TMenuItem;
menuRemoveColumn: TMenuItem; menuRemoveColumn: TMenuItem;
menuClearColumns: TMenuItem;
menuMoveUpColumn: TMenuItem; menuMoveUpColumn: TMenuItem;
menuMoveDownColumn: TMenuItem; menuMoveDownColumn: TMenuItem;
chkCharsetConvert: TCheckBox; chkCharsetConvert: TCheckBox;
@ -79,7 +77,6 @@ type
procedure Modification(Sender: TObject); procedure Modification(Sender: TObject);
procedure btnAddColumnClick(Sender: TObject); procedure btnAddColumnClick(Sender: TObject);
procedure btnRemoveColumnClick(Sender: TObject); procedure btnRemoveColumnClick(Sender: TObject);
procedure btnClearColumnsClick(Sender: TObject);
procedure listColumnsBeforePaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas); procedure listColumnsBeforePaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas);
procedure listColumnsFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex); procedure listColumnsFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex);
procedure btnHelpClick(Sender: TObject); procedure btnHelpClick(Sender: TObject);
@ -253,7 +250,7 @@ begin
comboCollation.Items.Clear; comboCollation.Items.Clear;
Mainform.GetCollations(comboCollation.Items); Mainform.GetCollations(comboCollation.Items);
FAlterTableName := AlterTableName; FAlterTableName := AlterTableName;
btnClearColumnsClick(Self); Columns.Clear;
btnClearIndexesClick(Self); btnClearIndexesClick(Self);
tabALTERcode.TabVisible := FAlterTableName <> ''; tabALTERcode.TabVisible := FAlterTableName <> '';
@ -833,37 +830,29 @@ end;
procedure TfrmTableEditor.btnRemoveColumnClick(Sender: TObject); procedure TfrmTableEditor.btnRemoveColumnClick(Sender: TObject);
var var
i: Integer; i, FocusIndex: Integer;
n: PVirtualNode; SelCols: TWideStringList;
begin begin
// Remove selected column // Remove selected column(s)
n := listColumns.FocusedNode; SelCols := GetVTCaptions(listColumns, true, 1);
// Remember focused node index
if Assigned(listColumns.FocusedNode) then
FocusIndex := listColumns.FocusedNode.Index
else
FocusIndex := listColumns.GetFirstSelected.Index;
// Set empty value for name=val column name pairs
for i:=0 to ColumnNames.Count-1 do begin for i:=0 to ColumnNames.Count-1 do begin
if ColumnNames.ValueFromIndex[i] = Columns[n.Index] then begin if SelCols.IndexOf(ColumnNames.ValueFromIndex[i]) > -1 then begin
ColumnNames[i] := ColumnNames.Names[i] + ColumnNames.NameValueSeparator; ColumnNames[i] := ColumnNames.Names[i] + ColumnNames.NameValueSeparator;
break;
end; end;
end; end;
Columns.Delete(n.Index); for i:=0 to SelCols.Count-1 do begin
if (not Assigned(n)) and (Columns.Count > 0) then Columns.Delete(Columns.IndexOf(SelCols[i]));
SelectNode(listColumns, Columns.Count-1); end;
end; if Columns.Count > 0 then
SelectNode(listColumns, Min(FocusIndex, Columns.Count-1));
ValidateColumnControls;
procedure TfrmTableEditor.btnClearColumnsClick(Sender: TObject);
var i: Integer;
begin
// Set empty values in changelist
for i:=0 to ColumnNames.Count - 1 do
ColumnNames[i] := ColumnNames.Names[i] + ColumnNames.NameValueSeparator;
// Column data gets freed below - end any editor which could cause AV's
if listColumns.IsEditing then
listColumns.CancelEditNode;
// I suspect Columns.Clear to be silly enough and leave its objects in memory,
// so we'll free them explicitely
for i := 0 to Columns.Count - 1 do
Columns.Objects[i].Free;
Columns.Clear;
end; end;
@ -965,13 +954,11 @@ procedure TfrmTableEditor.ValidateColumnControls;
var Node: PVirtualNode; var Node: PVirtualNode;
begin begin
Node := listColumns.FocusedNode; Node := listColumns.FocusedNode;
btnRemoveColumn.Enabled := Assigned(Node); btnRemoveColumn.Enabled := listColumns.SelectedCount > 0;
btnClearColumns.Enabled := Columns.Count > 0;
btnMoveUpColumn.Enabled := Assigned(Node) and (Node <> listColumns.GetFirst); btnMoveUpColumn.Enabled := Assigned(Node) and (Node <> listColumns.GetFirst);
btnMoveDownColumn.Enabled := Assigned(Node) and (Node <> listColumns.GetLast); btnMoveDownColumn.Enabled := Assigned(Node) and (Node <> listColumns.GetLast);
menuRemoveColumn.Enabled := btnRemoveColumn.Enabled; menuRemoveColumn.Enabled := btnRemoveColumn.Enabled;
menuClearColumns.Enabled := btnClearColumns.Enabled;
menuMoveUpColumn.Enabled := btnMoveUpColumn.Enabled; menuMoveUpColumn.Enabled := btnMoveUpColumn.Enabled;
menuMoveDownColumn.Enabled := btnMoveDownColumn.Enabled; menuMoveDownColumn.Enabled := btnMoveDownColumn.Enabled;
end; end;
@ -1208,8 +1195,8 @@ begin
if Node.Index = idx then begin if Node.Index = idx then begin
VT.FocusedNode := Node; VT.FocusedNode := Node;
VT.Selected[Node] := True; VT.Selected[Node] := True;
break; end else
end; VT.Selected[Node] := False;
Node := VT.GetNextSibling(Node); Node := VT.GetNextSibling(Node);
end; end;
end; end;
@ -1689,15 +1676,16 @@ var
IndexName, IndexType: WideString; IndexName, IndexType: WideString;
Item: TMenuItem; Item: TMenuItem;
PrimaryKeyExists, PrimaryKeyExists,
ColumnFocused: Boolean; ColumnsSelected: Boolean;
IndexParts: TWideStringList; IndexParts: TWideStringList;
Node: PVirtualNode;
begin begin
ColumnFocused := Assigned(ListColumns.FocusedNode); ColumnsSelected := ListColumns.SelectedCount > 0;
menuAddToIndex.Clear; menuAddToIndex.Clear;
menuCreateIndex.Clear; menuCreateIndex.Clear;
menuAddToIndex.Enabled := ColumnFocused; menuAddToIndex.Enabled := ColumnsSelected;
menuCreateIndex.Enabled := ColumnFocused; menuCreateIndex.Enabled := ColumnsSelected;
if not ColumnFocused then if not ColumnsSelected then
Exit; Exit;
// Auto create submenu items for "Add to index" ... // Auto create submenu items for "Add to index" ...
@ -1709,9 +1697,18 @@ begin
else else
IndexName := IndexName + ' ('+IndexType+')'; IndexName := IndexName + ' ('+IndexType+')';
Item := AddItem(menuAddToIndex, IndexName, GetIndexIcon(i)); Item := AddItem(menuAddToIndex, IndexName, GetIndexIcon(i));
// Disable menuitem if column is already part of index // Disable menuitem if all selected columns are already part of this index,
// enable it if one or more selected columns are not.
Item.Enabled := False;
IndexParts := TWideStringList(Indexes.Objects[i]); IndexParts := TWideStringList(Indexes.Objects[i]);
Item.Enabled := IndexParts.IndexOf(Columns[ListColumns.FocusedNode.Index]) = -1; Node := listColumns.GetFirstSelected;
while Assigned(Node) do begin
if IndexParts.IndexOf(Columns[Node.Index]) = -1 then begin
Item.Enabled := True;
Break;
end;
Node := listColumns.GetNextSelected(Node);
end;
end; end;
menuAddToIndex.Enabled := menuAddToIndex.Count > 0; menuAddToIndex.Enabled := menuAddToIndex.Count > 0;
@ -1730,40 +1727,41 @@ var
Item: TMenuItem; Item: TMenuItem;
i: Integer; i: Integer;
IndexName, IndexType, IndexName, IndexType,
NewName, NewType, NewPart: WideString; NewName, NewType: WideString;
IndexParts: TWideStringlist; IndexParts, NewParts: TWideStringlist;
begin begin
// Auto create index or add column to existing one by rightclicking a column // Auto create index or add columns to existing one by rightclicking a column
Item := (Sender as TMenuItem); Item := (Sender as TMenuItem);
NewPart := Columns[ListColumns.FocusedNode.Index]; NewParts := GetVTCaptions(listColumns, True, 1);
if Item.Parent = menuCreateIndex then begin if Item.Parent = menuCreateIndex then begin
NewName := 'Index '+IntToStr(Indexes.Count+1); NewName := 'Index '+IntToStr(Indexes.Count+1);
// Remove auto hotkeys // Remove auto hotkeys
NewType := StringReplace(Item.Caption, '&', '', [rfReplaceAll]); NewType := StringReplace(Item.Caption, '&', '', [rfReplaceAll]);
// Avoid creating a second key with the same column // Avoid creating a second key with the same columns
for i:=0 to Indexes.Count-1 do begin for i:=0 to Indexes.Count-1 do begin
IndexParts := TWideStringList(Indexes.Objects[i]); IndexParts := TWideStringList(Indexes.Objects[i]);
GetIndexInfo(i, IndexName, IndexType); GetIndexInfo(i, IndexName, IndexType);
if (IndexType = NewType) and (IndexParts.Count = 1) and (IndexParts[0] = NewPart) then begin if (IndexType = NewType) and (IndexParts.Text = NewParts.Text) then begin
if MessageDlg('Key already exists. Really create a second identical key? This will slow down queries on this table.', if MessageDlg('Key already exists. Really create another identical one?'+CRLF+CRLF+
'This will increase disk usage and probably slow down queries on this table.',
mtConfirmation, [mbYes, mbNo], 0) = mrNo then mtConfirmation, [mbYes, mbNo], 0) = mrNo then
Exit; Exit;
break; break;
end; end;
end; end;
IndexParts := TWideStringlist.Create; NewParts.OnChange := IndexesChange;
IndexParts.OnChange := IndexesChange; Indexes.AddObject(NewName+REGDELIM+NewType, NewParts);
// TODO: Enable multiselection in ListColumns so one can create a multicolumn key in two clicks
IndexParts.Add(NewPart);
Indexes.AddObject(NewName+REGDELIM+NewType, IndexParts);
PageControlMain.ActivePage := tabIndexes; PageControlMain.ActivePage := tabIndexes;
treeIndexes.Repaint; treeIndexes.Repaint;
SelectNode(treeIndexes, Indexes.Count-1); SelectNode(treeIndexes, Indexes.Count-1);
SelectNode(treeIndexes, 0, treeIndexes.FocusedNode); SelectNode(treeIndexes, 0, treeIndexes.FocusedNode);
end else begin end else begin
IndexParts := TWideStringlist(Indexes.Objects[Item.MenuIndex]);
PageControlMain.ActivePage := tabIndexes; PageControlMain.ActivePage := tabIndexes;
IndexParts.Add(NewPart); IndexParts := TWideStringlist(Indexes.Objects[Item.MenuIndex]);
for i:=0 to NewParts.Count-1 do begin
if IndexParts.IndexOf(NewParts[i]) = -1 then
IndexParts.Add(NewParts[i]);
end;
SelectNode(treeIndexes, Item.MenuIndex); SelectNode(treeIndexes, Item.MenuIndex);
treeIndexes.ReinitChildren(treeIndexes.FocusedNode, False); treeIndexes.ReinitChildren(treeIndexes.FocusedNode, False);
SelectNode(treeIndexes, IndexParts.Count-1, treeIndexes.FocusedNode); SelectNode(treeIndexes, IndexParts.Count-1, treeIndexes.FocusedNode);