diff options
author | graemeg <graemeg@ae50a9b5-8222-0410-bf8d-8a13f76226bf> | 2007-08-17 14:35:33 +0000 |
---|---|---|
committer | graemeg <graemeg@ae50a9b5-8222-0410-bf8d-8a13f76226bf> | 2007-08-17 14:35:33 +0000 |
commit | 003a991ccc0b05ce9a939d27313dd5ee0d9f4390 (patch) | |
tree | 551a6dfc94dfff01f77b84f19d5a255ce66f5606 /src | |
parent | 76df5b245da72230e5491c51e049c19337884ac1 (diff) | |
download | fpGUI-003a991ccc0b05ce9a939d27313dd5ee0d9f4390.tar.xz |
* Implemented a FileOpen and FileSave dialog. Both are the same class. It's
not 100% yet. See ToDo list in header of gui_dialogs unit.
* Minor bug fix in ComboBox component and added missing (required) properties.
* Fixed a bug in TfpgCustomGrid.Destroy. Creating a decendant of TfpgCustomGrid
caused a crash in the destructor.
* Fixed bug in ListBox where scrollbar did not move with mouse wheel input.
* Added a new FileDialog example project.
Diffstat (limited to 'src')
-rw-r--r-- | src/gui/gui_basegrid.pas | 10 | ||||
-rw-r--r-- | src/gui/gui_combobox.pas | 42 | ||||
-rw-r--r-- | src/gui/gui_customgrid.pas | 9 | ||||
-rw-r--r-- | src/gui/gui_dialogs.pas | 502 | ||||
-rw-r--r-- | src/gui/gui_grid.pas | 11 | ||||
-rw-r--r-- | src/gui/gui_listbox.pas | 4 |
6 files changed, 564 insertions, 14 deletions
diff --git a/src/gui/gui_basegrid.pas b/src/gui/gui_basegrid.pas index 338cd1f0..6f793ff7 100644 --- a/src/gui/gui_basegrid.pas +++ b/src/gui/gui_basegrid.pas @@ -106,6 +106,7 @@ type public constructor Create(AOwner: TComponent); override; destructor Destroy; override; + procedure Update; end; implementation @@ -954,10 +955,19 @@ end; destructor TfpgBaseGrid.Destroy; begin + FOnRowChange := nil; + FOnFocusChange := nil; FFont.Free; FHeaderFont.Free; inherited Destroy; end; +procedure TfpgBaseGrid.Update; +begin + UpdateScrollBars; + FollowFocus; + RePaint; +end; + end. diff --git a/src/gui/gui_combobox.pas b/src/gui/gui_combobox.pas index 75449c24..565a886c 100644 --- a/src/gui/gui_combobox.pas +++ b/src/gui/gui_combobox.pas @@ -27,37 +27,41 @@ type FInternalBtn: TfpgButton; FItems: TStringList; FOnChange: TNotifyEvent; + function GetFontDesc: string; procedure SetBackgroundColor(const AValue: TfpgColor); procedure SetDropDownCount(const AValue: integer); procedure DoDropDown; procedure InternalBtnClick(Sender: TObject); procedure InternalListBoxSelect(Sender: TObject); procedure SetFocusItem(const AValue: integer); + procedure SetFontDesc(const AValue: string); protected FMargin: integer; procedure SetEnabled(const AValue: boolean); override; property DropDownCount: integer read FDropDownCount write SetDropDownCount default 8; procedure HandleLMouseDown(x, y: integer; shiftstate: TShiftState); override; procedure HandlePaint; override; - property Items: TStringList read FItems; + property Items: TStringList read FItems; {$Note Make this read/write } property FocusItem: integer read FFocusItem write SetFocusItem; - property Font: TfpgFont read FFont; property BackgroundColor: TfpgColor read FBackgroundColor write SetBackgroundColor; - function Text: string; + property FontDesc: string read GetFontDesc write SetFontDesc; property OnChange: TNotifyEvent read FOnChange write FOnChange; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; + function Text: string; procedure AfterConstruction; override; + property Font: TfpgFont read FFont; end; TfpgComboBox = class(TfpgCustomComboBox) published + property BackgroundColor; property DropDownCount; - property Items; property FocusItem; - property BackgroundColor; + property FontDesc; + property Items; property OnChange; end; @@ -187,6 +191,11 @@ begin end; end; +function TfpgCustomComboBox.GetFontDesc: string; +begin + Result := FFont.FontDesc; +end; + procedure TfpgCustomComboBox.DoDropDown; var pt: TPoint; @@ -241,11 +250,29 @@ begin FOnChange(self); end; +{ Focusitem is 1 based and NOT 0 based like the Delphi ItemIndex property. + So at startup, FocusItem = 0 which means nothing is selected. If FocusItem = 1 + it means the first item is selected etc. } procedure TfpgCustomComboBox.SetFocusItem(const AValue: integer); begin if FFocusItem = AValue then Exit; //==> FFocusItem := AValue; + + // do some limit check corrections + if FFocusItem < 0 then + FFocusItem := 0 // nothing is selected + else if FFocusItem > FItems.Count then + FFocusItem := FItems.Count; + + RePaint; +end; + +procedure TfpgCustomComboBox.SetFontDesc(const AValue: string); +begin + FFont.Free; + FFont := fpgGetFont(AValue); + RePaint; end; procedure TfpgCustomComboBox.SetEnabled(const AValue: boolean); @@ -302,7 +329,7 @@ begin Canvas.FillRectangle(r); // Draw select item's text - if FocusItem > -1 then + if FocusItem > 0 then fpgStyle.DrawString(Canvas, FMargin+1, FMargin, Text, Enabled); Canvas.EndDraw; @@ -323,7 +350,7 @@ begin FDropDownCount := 8; FWidth := 120; FHeight := 23; - FFocusItem := 0; + FFocusItem := 0; // nothing is selected FMargin := 3; FFont := fpgGetFont('#List'); @@ -350,6 +377,7 @@ begin FInternalBtn.Parent := self; FInternalBtn.ImageName := 'sys.sb.down'; FInternalBtn.ShowImage := True; + FInternalBtn.Anchors := [anRight, anTop]; end; end; diff --git a/src/gui/gui_customgrid.pas b/src/gui/gui_customgrid.pas index 58c21f3d..1cda07ef 100644 --- a/src/gui/gui_customgrid.pas +++ b/src/gui/gui_customgrid.pas @@ -110,8 +110,8 @@ begin while n > AValue do begin TGridColumn(FColumns.Items[n-1]).Free; + FColumns.Delete(n-1); dec(n); - FColumns.Count := n; end; end; UpdateScrollBars; @@ -170,7 +170,12 @@ end; destructor TfpgCustomGrid.Destroy; begin - SetColumnCount(0); + while FColumns.Count > 0 do + begin + TGridColumn(FColumns.Items[0]).Free; + FColumns.Delete(0); + end; + FColumns.Free; inherited Destroy; end; diff --git a/src/gui/gui_dialogs.pas b/src/gui/gui_dialogs.pas index 76648a68..a99a40a0 100644 --- a/src/gui/gui_dialogs.pas +++ b/src/gui/gui_dialogs.pas @@ -6,6 +6,14 @@ unit gui_dialogs; {$mode objfpc}{$H+} +{ + TODO: + * Try and abstract the code to remove all IFDEF's + * Combobox dropdown in FileDialog doesn't function to do ModolForm being used. + * File Selection not working 100% in FileDialog + * Moving through directories not working 100% yet in FileDialog. +} + {.$Define DEBUG} interface @@ -19,7 +27,10 @@ uses gui_label, gui_listbox, gui_checkbox, - gui_edit; + gui_edit, + gui_grid, + gui_combobox, + gui_bevel; type @@ -92,6 +103,50 @@ type { This well set the sample text or font preview text to AText.} procedure SetSampleText(AText: string); end; + + + TfpgFileDialog = class(TfpgBaseDialog) + private + FOpenMode: boolean; + FFilterList: TStringList; + FFilter: string; + procedure SetFilter(const Value: string); + function GetShowHidden: boolean; + procedure SetShowHidden(const Value: boolean); + procedure ListChanged(Sender: TObject; ARow: integer); + procedure InitializeComponents; + protected + procedure HandleKeyPress(var keycode: word; var shiftstate: TShiftState; var consumed: boolean); override; + procedure btnOKClick(Sender: TObject); override; + procedure SetCurrentDirectory(const ADir: string); + public + chlDir: TfpgComboBox; + grid: TfpgFileGrid; + btnUpDir: TfpgButton; + btnDirNew: TfpgButton; + btnShowHidden: TfpgButton; + panel1: TfpgBevel; + lbFileInfo: TfpgLabel; + edFilename: TfpgEdit; + chlFilter: TfpgComboBox; + lb1: TfpgLabel; + lb2: TfpgLabel; + FileName: string; + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure DirChange(Sender: TObject); + procedure FilterChange(Sender: TObject); + procedure GridDblClick(Sender: TObject; x, y: integer; var btnstate, shiftstate: word); + procedure UpDirClick(Sender: TObject); + function SelectFile(const AFilename: string): boolean; + procedure ProcessFilterString; + function GetFileFilter: string; + property Filter: string read FFilter write SetFilter; + function RunOpenFile: boolean; + function RunSaveFile: boolean; + property ShowHidden: boolean read GetShowHidden write SetShowHidden; + end; + { A convenience function to show a message using the TfpgMessageBox class.} procedure ShowMessage(AMessage, ATitle: string); overload; @@ -106,9 +161,10 @@ implementation uses gfxbase, + gfx_widget, gfx_utf8utils; - - + + procedure ShowMessage(AMessage, ATitle: string); var frm: TfpgMessageBox; @@ -631,5 +687,445 @@ begin edSample.Text := FSampleText; end; +{ TfpgFileDialog } + +procedure TfpgFileDialog.ListChanged(Sender: TObject; ARow: integer); +var + s : string; +begin + if grid.CurrentEntry = nil then + Exit; //==> + s := grid.CurrentEntry.Name; + + if grid.CurrentEntry.IsLink then + s := s + ' -> ' + grid.CurrentEntry.LinkTarget; + + if grid.CurrentEntry.EntryType <> etDir then + edFileName.Text := grid.CurrentEntry.Name; + + btnOK.Enabled := grid.CurrentEntry.EntryType = etFile; + + lbFileInfo.Text := s; +end; + +procedure TfpgFileDialog.SetFilter(const Value: string); +begin + FFilter := Value; + ProcessFilterString; +end; + +function TfpgFileDialog.GetShowHidden: boolean; +begin + Result := btnShowHidden.Down; +end; + +procedure TfpgFileDialog.SetShowHidden(const Value: boolean); +begin + btnShowHidden.Down := Value; +end; + +procedure TfpgFileDialog.InitializeComponents; +begin + chlDir := TfpgComboBox.Create(self); + with chlDir do + begin + SetPosition(8, 12, 526, 22); + Anchors := [anLeft, anRight, anTop]; + FontDesc := '#List'; + OnChange := @DirChange; + end; + + grid := TfpgFileGrid.Create(self); + with grid do + begin + SetPosition(8, 44, 622, 200); + Anchors := [anLeft, anRight, anTop, anBottom]; + OnRowChange := @ListChanged; +// OnDoubleClick := @GridDblClick; + end; + + btnUpDir := TfpgButton.Create(self); + with btnUpDir do + begin + SetPosition(540, 11, 26, 24); + Anchors := [anRight, anTop]; + Text := ''; + FontDesc := '#Label1'; + ImageName := 'stdimg.folderup'; + ModalResult := 0; + Focusable := False; + OnClick := @UpDirClick; + end; + + btnDirNew := TfpgButton.Create(self); + with btnDirNew do + begin + SetPosition(572, 11, 26, 24); + Anchors := [anRight, anTop]; + Text := ''; + FontDesc := '#Label1'; + ImageName := 'stdimg.foldernew'; + ModalResult := 0; + Focusable := False; + end; + + btnShowHidden := TfpgButton.Create(self); + with btnShowHidden do + begin + SetPosition(604, 11, 26, 24); + Anchors := [anRight, anTop]; + Text := ''; + FontDesc := '#Label1'; + ImageName := 'stdimg.hidden'; + ModalResult := 0; + Focusable := False; + GroupIndex := 1; + AllowAllUp := True; + OnClick := @DirChange; + end; + + { Create lower Panel details } + + panel1 := TfpgBevel.Create(self); + with panel1 do + begin + SetPosition(8, 253, 622, 25); + Anchors := [anLeft, anRight, anBottom]; + Shape := bsBox; + Style := bsLowered; + end; + + lbFileInfo := TfpgLabel.Create(panel1); + with lbFileInfo do + begin + SetPosition(5, 4, 609, 16); + Anchors := [anLeft, anRight, anTop]; + Text := ' '; + FontDesc := '#Label1'; + end; + + edFilename := TfpgEdit.Create(self); + with edFilename do + begin + SetPosition(8, 301, 622, 22); + Anchors := [anLeft, anRight, anBottom]; + Text := ''; + FontDesc := '#Edit1'; + end; + + { Filter section } + + chlFilter := TfpgComboBox.Create(self); + with chlFilter do + begin + SetPosition(8, 345, 622, 22); + Anchors := [anLeft, anRight, anBottom]; + FontDesc := '#List'; + OnChange := @FilterChange; + end; + + lb1 := TfpgLabel.Create(self); + with lb1 do + begin + SetPosition(8, 283, 80, 16); + Anchors := [anLeft, anBottom]; + Text := 'Filename:'; + FontDesc := '#Label1'; + end; + + lb2 := TfpgLabel.Create(self); + with lb2 do + begin + SetPosition(8, 327, 64, 16); + Anchors := [anLeft, anBottom]; + Text := 'File type:'; + FontDesc := '#Label1'; + end; + + ActiveWidget := grid; + FileName := ''; + Filter := 'All Files (*)|*'; +end; + +procedure TfpgFileDialog.HandleKeyPress(var keycode: word; var shiftstate: TShiftState; var consumed: boolean); +var + e: TFileEntry; +begin + if not consumed then + begin + if (keycode = keyReturn) and (ActiveWidget = grid) then + begin + e := grid.CurrentEntry; + if (e <> nil) and (e.EntryType = etDir) then + begin + SetCurrentDirectory(e.Name); + consumed := True; + end; + end; + end; + if not consumed then + inherited HandleKeyPress(keycode, shiftstate, consumed); +end; + +procedure TfpgFileDialog.btnOKClick(Sender: TObject); +begin + if not FOpenMode or SysUtils.FileExists(edFileName.Text) then + begin + ModalResult := 1; + end; + + if ModalResult > 0 then + FileName := ExpandFileName(edFileName.Text); +end; + +constructor TfpgFileDialog.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + WindowTitle := 'File Selection'; + Width := 640; + Height := 410; // 460; + WindowPosition := wpScreenCenter; + FSpacing := 10; + + FFilterList := TStringList.Create; + + InitializeComponents; + + // position standard dialog buttons + btnCancel.Left := Width - FDefaultButtonWidth - FSpacing; + btnCancel.Top := Height - btnCancel.Height - FSpacing; + btnOK.Left := btnCancel.Left - FDefaultButtonWidth - 6; + btnOK.Top := btnCancel.Top; +end; + +destructor TfpgFileDialog.Destroy; +begin + FFilterList.Free; + inherited Destroy; +end; + +procedure TfpgFileDialog.DirChange(Sender: TObject); +begin + SetCurrentDirectory(chlDir.Text); +end; + +procedure TfpgFileDialog.FilterChange(Sender: TObject); +begin + SetCurrentDirectory('.'); +end; + +procedure TfpgFileDialog.GridDblClick(Sender: TObject; x, y: integer; + var btnstate, shiftstate: word); +begin + +end; + +procedure TfpgFileDialog.UpDirClick(Sender: TObject); +begin + SetCurrentDirectory('..'); +end; + +procedure TfpgFileDialog.SetCurrentDirectory(const ADir: string); +var + ds: string; + n: integer; + rootadd: integer; + fsel: string; +{$ifdef Win32} + drvind: integer; + drvs: string; +{$endif} +begin + GetDir(0, ds); + fsel := ExtractFileName(ds); + + if not SetCurrentDir(ADir) then + begin + ShowMessage('Could not open the directory ' + ADir, 'Error'); + Exit; //==> + end; + + chlDir.Items.Clear; + if ADir <> '..' then + fsel := ''; + + rootadd := 1; + + {$IFDEF MSWINDOWS} + // making drive list 1 + drvind := -1; + if Copy(ds, 2, 1) = ':' then + drvind := ord(UpCase(ds[1]))-ord('A'); + n := 0; + while n < drvind do + begin + drvs := chr(n+ord('A'))+':\'; + if Windows.GetDriveType(PChar(drvs)) <> 1 then + begin + chlDir.Items.Add(u8(drvs)); + end; + inc(n); + end; + {$ENDIF} + + {$IFDEF UNIX} + if Copy(ds, 1, 1) <> DirectorySeparator then + ds := DirectorySeparator + ds; + {$ENDIF} + + n := 1; + while n < Length(ds) do + begin + if ds[n] = DirectorySeparator then + begin + chlDir.Items.Add(Copy(ds, 1, n-1+rootadd)); + rootadd := 0; + end; + inc(n); + end; + + chlDir.Items.Add(ds); + chlDir.FocusItem := chlDir.Items.Count; + + {$IFDEF MSWINDOWS} + // making drive list 2 + n := drvind+1; + if n < 0 then n := 0; + while n <= 25 do + begin + drvs := chr(n+ord('A'))+':\'; + if Windows.GetDriveType(PChar(drvs)) <> 1 then + begin + chlDir.Items.Add(u8(drvs)); + end; + inc(n); + end; + {$ENDIF} + + grid.FileList.ReadDirectory(GetFileFilter, ShowHidden); + grid.FileList.Sort(soFileName); + grid.Update; + + if fsel <> '' then + SelectFile(fsel) + else + grid.FocusRow := 1; +end; + +function TfpgFileDialog.SelectFile(const AFilename: string): boolean; +var + n : integer; +begin + for n:=1 to grid.FileList.Count do + begin + if grid.FileList.Entry[n].Name = AFilename then + begin + grid.FocusRow := n; + Result := True; + Exit; //==> + end; + end; + Result := False; +end; + +procedure TfpgFileDialog.ProcessFilterString; +var + p: integer; + s: string; + fs: string; + fm: string; +begin + s := FFilter; + FFilterList.Clear; + chlFilter.Items.Clear; + + repeat + fs := ''; + fm := ''; + p := pos('|', s); + if p > 0 then + begin + fs := Copy(s, 1, p-1); + Delete(s, 1, p); + p := pos('|', s); + if p > 0 then + begin + fm := Copy(s, 1, p-1); + Delete(s, 1, p); + end + else + begin + fm := s; + s := ''; + end; + end; + + if (fs <> '') and (fm <> '') then + begin + chlFilter.Items.Add(fs); + FFilterList.Add(fm); + end; + until (fs = '') or (fm = ''); { repeat/until } +end; + +function TfpgFileDialog.GetFileFilter: string; +var + i: integer; +begin + i := chlFilter.FocusItem; + if (i > 0) and (i <= FFilterList.Count) then + Result := FFilterList[i-1] + else + Result := '*'; +end; + +function TfpgFileDialog.RunOpenFile: boolean; +var + sdir: string; + fname: string; +begin + FOpenMode := True; + sdir := ExtractFileDir(FileName); + if sdir = '' then + sdir := '.'; + SetCurrentDirectory(sdir); + fname := ExtractFileName(FileName); + if not SelectFile(fname) then + edFilename.Text := fname; + + WindowTitle := 'Open File...'; + btnOK.ImageName := 'stdimg.open'; + btnOK.Text := 'Open'; + + if ShowModal > 0 then + Result := True + else + Result := False; +end; + +function TfpgFileDialog.RunSaveFile: boolean; +var + sdir: string; + fname: string; +begin + FOpenMode := False; + sdir := ExtractFileDir(FileName); + if sdir = '' then + sdir := '.'; + SetCurrentDirectory(sdir); + fname := ExtractFileName(FileName); + if not SelectFile(fname) then + edFilename.Text := fname; + + WindowTitle := 'Save File...'; + btnOK.ImageName := 'stdimg.save'; + btnOK.Text := 'Save'; + + if ShowModal > 0 then + Result := True + else + Result := False; +end; + end. diff --git a/src/gui/gui_grid.pas b/src/gui/gui_grid.pas index f69bd964..fb203677 100644 --- a/src/gui/gui_grid.pas +++ b/src/gui/gui_grid.pas @@ -100,6 +100,12 @@ type property FixedFont: TfpgFont read FFixedFont; property FileList: TFileList read FFileList; property DefaultRowHeight; + published + property RowCount; + property ColumnCount; + property Columns; + property FocusRow; + property OnRowChange; end; @@ -343,7 +349,8 @@ end; procedure TFileList.Sort(AOrder: TFileListSortOrder); var newl: TList; - n, i: integer; + n: integer; + i: integer; e: TFileEntry; function IsBefore(newitem, item: TFileEntry): boolean; @@ -505,6 +512,7 @@ begin FFileList := TFileList.Create; inherited Create(AOwner); ColumnCount := 0; + RowCount := 0; FFixedFont := fpgGetFont('Courier New-9'); {$Note Abstract this! No IFDEF's allowed!!! } @@ -530,6 +538,7 @@ end; destructor TfpgFileGrid.Destroy; begin + OnRowChange := nil; FFixedFont.Free; FFileList.Free; inherited Destroy; diff --git a/src/gui/gui_listbox.pas b/src/gui/gui_listbox.pas index 825c36de..0933c211 100644 --- a/src/gui/gui_listbox.pas +++ b/src/gui/gui_listbox.pas @@ -184,7 +184,8 @@ begin VHeight := Height - 4; HWidth := Width - 4; - if FScrollBar.Visible then Dec(HWidth, FScrollBar.Width); + if FScrollBar.Visible then + Dec(HWidth, FScrollBar.Width); FScrollBar.Top := 2; FScrollBar.Left := Width - FScrollBar.Width - 2; @@ -214,6 +215,7 @@ begin FScrollBar.SliderSize := 1; FScrollBar.Max := ItemCount-pn+1; FScrollBar.Position := FFirstItem; + FScrollBar.RepaintSlider; end; end; |