diff --git a/Source/UnSwClient.pas b/Source/UnSwClient.pas index 1d4a4f2..429e4ca 100644 --- a/Source/UnSwClient.pas +++ b/Source/UnSwClient.pas @@ -168,9 +168,11 @@ end; procedure TUnitSwitcherHook.NewExecute(Sender: TObject); var activeIndex: Integer; - project: IOTAProject; - moduleIndex: Integer; activeUnit: TUnSwUnit; + itemIndex: Integer; + moduleIndex: Integer; + project: IOTAProject; + selectedUnits: TUnSwUnitList; unitList: TUnSwUnitList; begin @@ -190,10 +192,15 @@ begin if activeIndex > -1 then activeUnit := unitList[activeIndex]; - activeUnit := TfrmUnSwDialog.Execute(unitList, (Sender = FViewFormAction), - activeUnit); - if Assigned(activeUnit) then - activeUnit.Activate((Sender = FViewUnitAction)); + selectedUnits := TfrmUnSwDialog.Execute(unitList, (Sender = FViewFormAction), + activeUnit); + if Assigned(selectedUnits) then + try + for itemIndex := 0 to Pred(selectedUnits.Count) do + selectedUnits[itemIndex].Activate((Sender = FViewUnitAction)); + finally + FreeAndNil(selectedUnits); + end; finally FreeAndNil(unitList); end; diff --git a/Source/UnSwConfiguration.dfm b/Source/UnSwConfiguration.dfm index ae13662..6aaaae4 100644 --- a/Source/UnSwConfiguration.dfm +++ b/Source/UnSwConfiguration.dfm @@ -27,7 +27,6 @@ object frmUnSwConfiguration: TfrmUnSwConfiguration ActivePage = tsGeneral Anchors = [akLeft, akTop, akRight, akBottom] TabOrder = 0 - ExplicitHeight = 299 object tsGeneral: TTabSheet Caption = 'General' object chkCustomColor: TCheckBox @@ -263,17 +262,16 @@ object frmUnSwConfiguration: TfrmUnSwConfiguration Caption = 'Version 0.2' end object TLabel - Left = 56 - Top = 106 + Left = 135 + Top = 23 Width = 145 Height = 13 Anchors = [akLeft, akBottom] Caption = 'Copyright '#169' 2006 X'#178'Software' - ExplicitTop = 196 end object TLabel Left = 56 - Top = 130 + Top = 90 Width = 225 Height = 41 Anchors = [akLeft, akRight, akBottom] @@ -282,20 +280,34 @@ object frmUnSwConfiguration: TfrmUnSwConfiguration 'UnitSwitcher is released as open-source under the zlib/libpng OS' + 'I-approved license. See license.txt for details.' WordWrap = True - ExplicitTop = 220 end object TLabel Left = 56 - Top = 56 + Top = 52 Width = 225 Height = 29 Anchors = [akLeft, akTop, akRight] AutoSize = False Caption = - 'Many thanks to Richard L. for the idea, feedback and beta testin' + - 'g.' + 'Many thanks to Richard Lichtendahl for the idea, feedback and be' + + 'ta testing.' WordWrap = True end + object lblBugReport: TLabel + Left = 56 + Top = 156 + Width = 75 + Height = 13 + Cursor = crHandPoint + Caption = 'Report a bug...' + Font.Charset = DEFAULT_CHARSET + Font.Color = clBlue + Font.Height = -11 + Font.Name = 'Tahoma' + Font.Style = [fsUnderline] + ParentFont = False + OnClick = lblBugReportClick + end end end object btnCancel: TButton @@ -321,7 +333,7 @@ object frmUnSwConfiguration: TfrmUnSwConfiguration end object dlgColor: TColorDialog Options = [cdFullOpen] - Left = 8 - Top = 216 + Left = 12 + Top = 176 end end diff --git a/Source/UnSwConfiguration.pas b/Source/UnSwConfiguration.pas index e65bb34..8378c5c 100644 --- a/Source/UnSwConfiguration.pas +++ b/Source/UnSwConfiguration.pas @@ -28,6 +28,7 @@ type chkCustomColor: TCheckBox; dlgColor: TColorDialog; imgAbout: TImage; + lblBugReport: TLabel; lblDataModuleColor: TLabel; lblFormColor: TLabel; lblProjectColor: TLabel; @@ -37,8 +38,9 @@ type pnlCustomColor: TPanel; tsAbout: TTabSheet; tsGeneral: TTabSheet; - + procedure chkCustomColorClick(Sender: TObject); + procedure lblBugReportClick(Sender: TObject); procedure PickColor(Sender: TObject); private FLabels: array[0..3] of TLabel; @@ -53,6 +55,9 @@ type implementation uses + ShellAPI, + Windows, + UnSwSettings; {$R *.dfm} @@ -86,6 +91,11 @@ begin end; +procedure TfrmUnSwConfiguration.lblBugReportClick(Sender: TObject); +begin + ShellExecute(0, 'open', 'http://projects.kamadev.net/', nil, nil, SW_SHOWNORMAL); +end; + procedure TfrmUnSwConfiguration.LoadSettings(); begin chkCustomColor.Checked := Settings.Colors.Enabled; diff --git a/Source/UnSwDialog.dfm b/Source/UnSwDialog.dfm index 42d43a9..cade155 100644 --- a/Source/UnSwDialog.dfm +++ b/Source/UnSwDialog.dfm @@ -27,6 +27,7 @@ object frmUnSwDialog: TfrmUnSwDialog OldCreateOrder = False Position = poScreenCenter OnResize = FormResize + OnShow = FormShow PixelsPerInch = 96 TextHeight = 13 object sbStatus: TStatusBar @@ -48,8 +49,6 @@ object frmUnSwDialog: TfrmUnSwDialog BevelOuter = bvNone BorderWidth = 4 TabOrder = 0 - ExplicitWidth = 299 - ExplicitHeight = 317 object pnlSearch: TPanel Left = 4 Top = 4 @@ -80,6 +79,7 @@ object frmUnSwDialog: TfrmUnSwDialog Style = lbVirtualOwnerDraw Align = alClient ItemHeight = 20 + MultiSelect = True TabOrder = 1 OnData = lstUnitsData OnDblClick = lstUnitsDblClick @@ -572,4 +572,13 @@ object frmUnSwDialog: TfrmUnSwDialog E003E003FFFFF000E007E007FFFFF00000000000000000000000000000000000 000000000000} end + object alMain: TActionList + Left = 36 + Top = 32 + object actSelectAll: TAction + Caption = 'Select &All' + ShortCut = 16449 + OnExecute = actSelectAllExecute + end + end end diff --git a/Source/UnSwDialog.pas b/Source/UnSwDialog.pas index 9e7f4f2..3d760c2 100644 --- a/Source/UnSwDialog.pas +++ b/Source/UnSwDialog.pas @@ -8,6 +8,7 @@ unit UnSwDialog; interface uses + ActnList, Classes, ComCtrls, Controls, @@ -49,6 +50,10 @@ type pnlMain: TPanel; pnlSearch: TPanel; sbStatus: TStatusBar; + alMain: TActionList; + actSelectAll: TAction; + procedure FormShow(Sender: TObject); + procedure actSelectAllExecute(Sender: TObject); procedure FormResize(Sender: TObject); procedure btnConfigurationClick(Sender: TObject); @@ -72,18 +77,18 @@ type FStyleVisitor: TUnSwStyleVisitor; - function InternalExecute(): TUnSwUnit; + function InternalExecute(): TUnSwUnitList; procedure UpdateTypeFilter(); procedure UpdateList(); - function GetActiveUnit(): TUnSwUnit; + function GetActiveUnits(): TUnSwUnitList; procedure LoadSettings(); procedure SaveSettings(); public class function Execute(const AUnits: TUnSwUnitList; const AFormsOnly: Boolean; - const AActive: TUnSwUnit = nil): TUnSwUnit; + const AActive: TUnSwUnit = nil): TUnSwUnitList; end; implementation @@ -133,7 +138,7 @@ end; { TfrmUnSwDialog } class function TfrmUnSwDialog.Execute(const AUnits: TUnSwUnitList; const AFormsOnly: Boolean; - const AActive: TUnSwUnit): TUnSwUnit; + const AActive: TUnSwUnit): TUnSwUnitList; begin with Self.Create(nil) do try @@ -151,12 +156,18 @@ begin lstUnits.Invalidate(); end; +procedure TfrmUnSwDialog.FormShow(Sender: TObject); +begin + // Setting ListBox.Selected[x] won't work before OnShow... + UpdateTypeFilter(); +end; + function SortByName(Item1, Item2: Pointer): Integer; begin Result := CompareText(TUnSwUnit(Item1).Name, TUnSwUnit(Item2).Name) end; -function TfrmUnSwDialog.InternalExecute(): TUnSwUnit; +function TfrmUnSwDialog.InternalExecute(): TUnSwUnitList; begin Result := nil; FTypeFilteredList := TUnSwUnitList.Create(); @@ -177,12 +188,10 @@ begin end else Self.Caption := 'UnitSwitcher - View Unit'; - UpdateTypeFilter(); - FStyleVisitor := TUnSwStyleVisitor.Create(); try if Self.ShowModal() = mrOk then - Result := GetActiveUnit(); + Result := GetActiveUnits(); SaveSettings(); finally @@ -199,9 +208,12 @@ end; procedure TfrmUnSwDialog.UpdateList(); var activeUnit: TUnSwUnit; + activeUnits: TUnSwUnitList; + itemIndex: Integer; + listIndex: Integer; begin - activeUnit := GetActiveUnit(); + activeUnits := GetActiveUnits(); FInputFilteredList.Clone(FTypeFilteredList); FInputFilteredList.AcceptVisitor(FInputFilter); @@ -209,11 +221,21 @@ begin lstUnits.Count := FInputFilteredList.Count; if FInputFilteredList.Count > 0 then begin - if Assigned(activeUnit) then - lstUnits.ItemIndex := FInputFilteredList.IndexOf(activeUnit); + lstUnits.ClearSelection(); - if lstUnits.ItemIndex = -1 then - lstUnits.ItemIndex := 0; + if Assigned(activeUnits) then + try + for itemIndex := 0 to Pred(activeUnits.Count) do + begin + activeUnit := activeUnits[itemIndex]; + listIndex := FInputFilteredList.IndexOf(activeUnit); + if listIndex > -1 then + lstUnits.Selected[listIndex] := True; + end; + finally + FreeAndNil(activeUnits); + end else + lstUnits.Selected[0] := True; end; end; @@ -230,15 +252,27 @@ begin UpdateList(); end; -function TfrmUnSwDialog.GetActiveUnit(): TUnSwUnit; +function TfrmUnSwDialog.GetActiveUnits(): TUnSwUnitList; +var + itemIndex: Integer; + begin - Result := FActiveUnit; - if not Assigned(Result) then + Result := nil; + + if Assigned(FActiveUnit) then begin - if lstUnits.ItemIndex > -1 then - Result := FInputFilteredList[lstUnits.ItemIndex]; - end else - FActiveUnit := nil; + Result := TUnSwUnitList.Create(); + Result.OwnsObjects := False; + Result.Add(FActiveUnit); + FActiveUnit := nil; + end else if lstUnits.SelCount > 0 then + begin + Result := TUnSwUnitList.Create(); + Result.OwnsObjects := False; + for itemIndex := 0 to Pred(lstUnits.Items.Count) do + if lstUnits.Selected[itemIndex] then + Result.Add(FInputFilteredList[itemIndex]); + end; end; @@ -286,6 +320,11 @@ begin end; +procedure TfrmUnSwDialog.actSelectAllExecute(Sender: TObject); +begin + lstUnits.SelectAll(); +end; + procedure TfrmUnSwDialog.btnConfigurationClick(Sender: TObject); begin if TfrmUnSwConfiguration.Execute() then @@ -301,7 +340,9 @@ end; procedure TfrmUnSwDialog.edtSearchKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin - if (Shift = []) and (Key in [VK_UP, VK_DOWN, VK_PRIOR, VK_NEXT]) then + if ((Shift = []) and (Key in [VK_UP, VK_DOWN, VK_PRIOR, VK_NEXT])) or + ((Shift = [ssCtrl]) and (Key in [VK_UP, VK_DOWN, VK_HOME, VK_END])) or + ((Shift = [ssShift]) and (Key in [VK_UP, VK_DOWN, VK_PRIOR, VK_NEXT])) then lstUnits.Perform(WM_KEYDOWN, Key, 0); end; diff --git a/Source/UnSwObjects.pas b/Source/UnSwObjects.pas index 15f6079..f88d48e 100644 --- a/Source/UnSwObjects.pas +++ b/Source/UnSwObjects.pas @@ -115,6 +115,9 @@ type private FItems: TObjectList; + function GetOwnsObjects(): Boolean; + procedure SetOwnsObjects(const Value: Boolean); + function GetCount(): Integer; function GetItem(Index: Integer): TUnSwUnit; procedure SetItem(Index: Integer; Value: TUnSwUnit); @@ -136,6 +139,8 @@ type property Count: Integer read GetCount; property Items[Index: Integer]: TUnSwUnit read GetItem write SetItem; default; + property OwnsObjects: Boolean read GetOwnsObjects + write SetOwnsObjects; end; implementation @@ -179,35 +184,28 @@ end; procedure TUnSwUnit.OpenModule(const AModule: IOTAModule; const ASource: Boolean); -{$IFDEF DELPHI7} var editor: IOTAEditor; formEditor: IOTAFormEditor; + isForm: Boolean; moduleIndex: Integer; -{$ENDIF} begin - {$IFDEF DELPHI7} + formEditor := nil; for moduleIndex := 0 to Pred(AModule.ModuleFileCount) do begin editor := AModule.ModuleFileEditors[moduleIndex]; + isForm := Supports(editor, IOTAFormEditor); - if not ASource then - begin - if not Assigned(formEditor) then - Supports(editor, IOTAFormEditor, formEditor); - end else + if (not ASource) and (isForm) and (not Assigned(formEditor)) then + formEditor := (editor as IOTAFormEditor); + + if not isForm then editor.Show(); end; if Assigned(formEditor) then formEditor.Show(); - {$ELSE} - if ASource then - AModule.ShowFilename(AModule.FileName) - else - AModule.Show(); - {$ENDIF} end; @@ -411,4 +409,14 @@ begin FItems[Index] := Value; end; +function TUnSwUnitList.GetOwnsObjects(): Boolean; +begin + Result := FItems.OwnsObjects; +end; + +procedure TUnSwUnitList.SetOwnsObjects(const Value: Boolean); +begin + FItems.OwnsObjects := Value; +end; + end. diff --git a/license.txt b/license.txt new file mode 100644 index 0000000..fe51791 --- /dev/null +++ b/license.txt @@ -0,0 +1,23 @@ +UnitSwitcher is released under the zlib/libpng OSI-approved license. +For more information: http://www.opensource.org/ + +Copyright (c) 2006 X2Software +http://www.x2software.net/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from +the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software in a + product, an acknowledgment in the product documentation would be + appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + +3. This notice may not be removed or altered from any source distribution.