From 9d15123d91456fb87d20f0e022c795b69a1f8eae Mon Sep 17 00:00:00 2001 From: paul Date: Thu, 27 Dec 2007 09:51:27 +0000 Subject: [PATCH] - gtk: move dialogs related stuff to gtkwsdialogs and gtk2wsdialogs - gtk complete moving CreateComponent code to appropriate classes - lcl remove CreateComponent method since there is no more need in it git-svn-id: trunk@13478 - --- lcl/extdlgs.pas | 2 +- lcl/interfacebase.pp | 1 - lcl/interfaces/carbon/carbonint.pas | 1 - lcl/interfaces/carbon/carbonobject.inc | 13 - lcl/interfaces/fpgui/fpguiint.pp | 1 - lcl/interfaces/fpgui/fpguiobject.inc | 12 - lcl/interfaces/gtk/gtk1int.pp | 7 - lcl/interfaces/gtk/gtk1widgetset.inc | 182 +--- lcl/interfaces/gtk/gtkcallback.inc | 645 ------------- lcl/interfaces/gtk/gtkint.pp | 20 +- lcl/interfaces/gtk/gtkproc.pp | 16 - lcl/interfaces/gtk/gtkwidgetset.inc | 538 ----------- lcl/interfaces/gtk/gtkwsclistbox.pp | 64 +- lcl/interfaces/gtk/gtkwsdialogs.pp | 1182 ++++++++++++++++++++++- lcl/interfaces/gtk/gtkwsextdlgs.pp | 36 +- lcl/interfaces/gtk/gtkwsstdctrls.pp | 119 ++- lcl/interfaces/gtk2/gtk2int.pas | 19 +- lcl/interfaces/gtk2/gtk2widgetset.inc | 354 +------ lcl/interfaces/gtk2/gtk2wsdialogs.pp | 367 ++++++- lcl/interfaces/qt/qtint.pp | 1 - lcl/interfaces/qt/qtobject.inc | 12 - lcl/interfaces/win32/win32int.pp | 1 - lcl/interfaces/win32/win32object.inc | 13 - lcl/interfaces/win32/win32wscontrols.pp | 6 +- lcl/interfaces/wince/winceint.pp | 1 - lcl/interfaces/wince/winceobject.inc | 5 - lcl/interfaces/wince/wincewscontrols.pp | 6 +- lcl/widgetset/wscontrols.pp | 2 +- 28 files changed, 1760 insertions(+), 1866 deletions(-) diff --git a/lcl/extdlgs.pas b/lcl/extdlgs.pas index f68f246450..4254847582 100644 --- a/lcl/extdlgs.pas +++ b/lcl/extdlgs.pas @@ -1262,7 +1262,7 @@ begin end; -Initialization +initialization {$i extdlgs.lrs} end. diff --git a/lcl/interfacebase.pp b/lcl/interfacebase.pp index 4451f851ea..ae1b4a818d 100644 --- a/lcl/interfacebase.pp +++ b/lcl/interfacebase.pp @@ -96,7 +96,6 @@ type function IsHelpKey(Key: Word; Shift: TShiftState): Boolean; virtual; // create and destroy - function CreateComponent(Sender : TObject): THandle; virtual; abstract; function CreateTimer(Interval: integer; TimerFunc: TFNTimerProc): THandle; virtual; abstract; function DestroyTimer(TimerHandle: THandle): boolean; virtual; abstract; function AppHandle: Thandle; virtual; diff --git a/lcl/interfaces/carbon/carbonint.pas b/lcl/interfaces/carbon/carbonint.pas index 20753aa073..3828daf3c6 100644 --- a/lcl/interfaces/carbon/carbonint.pas +++ b/lcl/interfaces/carbon/carbonint.pas @@ -102,7 +102,6 @@ type function IsHelpKey(Key: Word; Shift: TShiftState): Boolean; override; // create and destroy - function CreateComponent(Sender : TObject): THandle; override; function CreateTimer(Interval: integer; TimerFunc: TFNTimerProc) : THandle; override; function DestroyTimer(TimerHandle: THandle) : boolean; override; function PrepareUserEvent(Handle: HWND; Msg: Cardinal; wParam: WParam; diff --git a/lcl/interfaces/carbon/carbonobject.inc b/lcl/interfaces/carbon/carbonobject.inc index 1552c60333..178e31f12d 100644 --- a/lcl/interfaces/carbon/carbonobject.inc +++ b/lcl/interfaces/carbon/carbonobject.inc @@ -976,19 +976,6 @@ begin Result := False; // help key is Cmd + ?, will be called directly on key press end; -{------------------------------------------------------------------------------ - Method: TCarbonWidgetSet.CreateComponent - Params: Sender - - Tells Carbon to create a control - Deprecated! Implement TCarbonWS*.CreateHandle method instead. - ------------------------------------------------------------------------------} -function TCarbonWidgetSet.CreateComponent(Sender: TObject): THandle; -begin - DebugLn('WARNING: TCarbonWidgetSet.CreateComponent is deprecated, should not be called!! Go whack somebody with a large throut!'); - Result := 0; -end; - {------------------------------------------------------------------------------ Method: TimerCallback Params: inTimer - Timer reference diff --git a/lcl/interfaces/fpgui/fpguiint.pp b/lcl/interfaces/fpgui/fpguiint.pp index ef2f13ede0..56c54d23c3 100644 --- a/lcl/interfaces/fpgui/fpguiint.pp +++ b/lcl/interfaces/fpgui/fpguiint.pp @@ -76,7 +76,6 @@ type // create and destroy - function CreateComponent(Sender : TObject): THandle; override; function CreateTimer(Interval: integer; TimerFunc: TFNTimerProc): THandle; override; function DestroyTimer(TimerHandle: THandle): boolean; override; diff --git a/lcl/interfaces/fpgui/fpguiobject.inc b/lcl/interfaces/fpgui/fpguiobject.inc index ccf992d3e7..b13c285fa5 100644 --- a/lcl/interfaces/fpgui/fpguiobject.inc +++ b/lcl/interfaces/fpgui/fpguiobject.inc @@ -198,18 +198,6 @@ begin Result:=false; end; -{------------------------------------------------------------------------------ - Function: TFpGuiWidgetSet.CreateComponent - Params: sender - object for which to create visual representation - Returns: nothing - - Deprecated, never call this function - ------------------------------------------------------------------------------} -function TFpGuiWidgetSet.CreateComponent(Sender : TObject): THandle; -begin - Result := 0; -end; - {------------------------------------------------------------------------------ Function: TFpGuiWidgetSet.IsValidDC Params: DC - handle to a device context (TFpGuiDeviceContext) diff --git a/lcl/interfaces/gtk/gtk1int.pp b/lcl/interfaces/gtk/gtk1int.pp index e8d377059d..8f22b9c37f 100644 --- a/lcl/interfaces/gtk/gtk1int.pp +++ b/lcl/interfaces/gtk/gtk1int.pp @@ -69,14 +69,7 @@ type { TGTK1WidgetSet } TGTK1WidgetSet = class(TGTKWidgetSet) - private - function CreateComboBox(ComboBoxObject: TObject): PGtkWidget; - function CreateCListBox(Sender: TObject): PGtkWidget; - function CreateListBox(Sender: TObject): PGtkWidget; - function CreateMemo(Sender: TObject): PGtkWidget; protected - function CreateComponentWidget(Sender: TObject; ACompStyle: Integer; - const ACaption: String): PGtkWidget; override; // temporary solution till all are created through createhandle function GetDeviceContextClass: TGtkDeviceContextClass; override; public procedure SetWidgetFont(const AWidget: PGtkWidget; const AFont: TFont); override; diff --git a/lcl/interfaces/gtk/gtk1widgetset.inc b/lcl/interfaces/gtk/gtk1widgetset.inc index 2293dc946d..9ba2b30997 100644 --- a/lcl/interfaces/gtk/gtk1widgetset.inc +++ b/lcl/interfaces/gtk/gtk1widgetset.inc @@ -24,161 +24,6 @@ // {$DEFINE ASSERT_IS_ON} {$ENDIF} -function TGTK1WidgetSet.CreateCListBox(Sender: TObject): PGtkWidget; -var - ScrolledWnd: PGtkScrolledWindow absolute Result; - CListBox: TCListBox absolute Sender; - - CList: Pointer; - n: Integer; -begin - Result := gtk_scrolled_window_new(nil, nil); - GTK_WIDGET_UNSET_FLAGS(ScrolledWnd^.hscrollbar, GTK_CAN_FOCUS); - GTK_WIDGET_UNSET_FLAGS(ScrolledWnd^.vscrollbar, GTK_CAN_FOCUS); - gtk_scrolled_window_set_policy(ScrolledWnd, - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - gtk_widget_show(Result); - - CList := gtk_clist_new(CListBox.ListColumns); - for n := 0 to CListBox.ListColumns - 1 do - gtk_clist_set_column_width(CList, n, (Max(0, CListBox.Width-10)) div CListBox.ListColumns); - - gtk_scrolled_window_add_with_viewport(ScrolledWnd, CList); - gtk_container_set_focus_vadjustment(CList, - gtk_scrolled_window_get_vadjustment(ScrolledWnd)); - gtk_container_set_focus_hadjustment(Clist, - gtk_scrolled_window_get_hadjustment(ScrolledWnd)); - gtk_widget_show(CList); - - SetMainWidget(Result, CList); - GetWidgetInfo(Result, True)^.CoreWidget := CList; - SetSelectionMode(Sender, Result, CListBox.MultiSelect, CListBox.ExtendedSelect); -end; - -{------------------------------------------------------------------------------- - function TGtk1WidgetSet.CreateComboBox(ComboBoxObject: TObject): Pointer; --------------------------------------------------------------------------------} -function TGtk1WidgetSet.CreateComboBox(ComboBoxObject: TObject): PGtkWidget; -var - ComboBox: TComboBox absolute ComboBoxObject; - Widget: PGtkCombo absolute Result; - - ItemList: TGtkListStringList; - GtkList: PGtkList; -begin - Result:= gtk_combo_new(); - - SetMainWidget(Result, Widget^.entry); - - gtk_combo_disable_activate(Widget); - gtk_combo_set_case_sensitive(Widget, GdkTrue); - - // Prevents the OnSelect event be fired after inserting the first item - // or deleting the selected item - GtkList:=PGtkList(Widget^.List); - if GtkList^.selection=nil then - gtk_list_set_selection_mode(GtkList,GTK_SELECTION_SINGLE) - else - gtk_list_set_selection_mode(GtkList,GTK_SELECTION_BROWSE); - - // Items - ItemList:= TGtkListStringList.Create(GtkList,ComboBox,False); - gtk_object_set_data(PGtkObject(Widget), GtkListItemLCLListTag, ItemList); - ItemList.Assign(ComboBox.Items); - ItemList.Sorted:= ComboBox.Sorted; - - // ItemIndex - if ComboBox.ItemIndex >= 0 then - gtk_list_select_item(GtkList, ComboBox.ItemIndex); - - // MaxLength - gtk_entry_set_max_length(PGtkEntry(Widget^.entry),guint16(ComboBox.MaxLength)); -end; - -{------------------------------------------------------------------------------- - function CreateComponentWidget --------------------------------------------------------------------------------} - -function TGTK1WidgetSet.CreateComponentWidget(Sender: TObject; ACompStyle: Integer; const ACaption: String): PGtkWidget; -begin - case ACompstyle of - csComboBox: - Result := CreateComboBox(Sender); - - csMemo: - Result := CreateMemo(Sender); - - csListBox, csCheckListBox: - Result := CreateListBox(Sender); - - csCListBox: - Result := CreateCListBox(Sender); - - else - Result := inherited CreateComponentWidget(Sender, ACompStyle, ACaption); - end; -end; - -function TGTK1WidgetSet.CreateListBox(Sender: TObject): PGtkWidget; -var - ScrolledWnd: PGtkScrolledWindow absolute Result; - ListBox: TCustomListBox absolute Sender; - - List: Pointer; -begin - Result := gtk_scrolled_window_new(nil, nil); - GTK_WIDGET_UNSET_FLAGS(ScrolledWnd^.hscrollbar, GTK_CAN_FOCUS); - GTK_WIDGET_UNSET_FLAGS(ScrolledWnd^.vscrollbar, GTK_CAN_FOCUS); - gtk_scrolled_window_set_policy(ScrolledWnd, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_widget_show(Result); - - List := gtk_list_new; - gtk_scrolled_window_add_with_viewport(ScrolledWnd, List); - gtk_container_set_focus_vadjustment(List, - gtk_scrolled_window_get_vadjustment(ScrolledWnd)); - gtk_container_set_focus_hadjustment(PGtkContainer(List), - gtk_scrolled_window_get_hadjustment(ScrolledWnd)); - gtk_widget_show(List); - - SetMainWidget(Result, List); - GetWidgetInfo(Result, True)^.CoreWidget := List; - - SetSelectionMode(Sender, Result, ListBox.MultiSelect, ListBox.ExtendedSelect); -end; - -function TGTK1WidgetSet.CreateMemo(Sender: TObject): PGtkWidget; -var - p: Pointer absolute Result; - Memo: TCustomMemo absolute Sender; - - textwidget: Pointer; -begin - P := gtk_scrolled_window_new(nil, nil); - textwidget := gtk_text_new(nil, nil); - gtk_container_add(p, textwidget); - - GTK_WIDGET_UNSET_FLAGS(PGtkScrolledWindow(p)^.hscrollbar, GTK_CAN_FOCUS); - GTK_WIDGET_UNSET_FLAGS(PGtkScrolledWindow(p)^.vscrollbar, GTK_CAN_FOCUS); - gtk_scrolled_window_set_policy(p, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_text_set_adjustments(textwidget, - gtk_scrolled_window_get_hadjustment(p), - gtk_scrolled_window_get_vadjustment(p)); - - SetMainWidget(p, textwidget); - GetWidgetInfo(p, True)^.CoreWidget := textwidget; - - gtk_text_set_editable(textwidget, not Memo.ReadOnly); - if Memo.WordWrap then - gtk_text_set_line_wrap(textwidget, GdkTrue) - else - gtk_text_set_line_wrap(textwidget, GdkFalse); - gtk_text_set_word_wrap(textwidget, GdkTrue); - - gtk_widget_show_all(P); - DebugLn(['TGtkWidgetSet.CreateComponent ',DbgSName(Sender),' ',GetWidgetDebugReport(p)]); -end; - function TGTK1WidgetSet.GetDeviceContextClass: TGtkDeviceContextClass; begin Result := TGtk1DeviceContext; @@ -194,21 +39,18 @@ var FontGdiObject: PGdiObject; begin - if GtkWidgetIsA(AWidget,GTKAPIWidget_GetType) then begin - // the GTKAPIWidget is self drawn, so no use to change the widget style. - exit; - end; + if GtkWidgetIsA(AWidget,GTKAPIWidget_GetType) then + Exit; // the GTKAPIWidget is self drawn, so no use to change the widget style. - if (GTK_WIDGET_REALIZED(AWidget)) then begin - WindowStyle := gtk_style_copy(gtk_widget_get_style (AWidget)); - end else begin - WindowStyle := gtk_style_copy(gtk_rc_get_style (AWidget)); - end; - if (Windowstyle = nil) then begin - Windowstyle := gtk_style_new ; - end; + if (GTK_WIDGET_REALIZED(AWidget)) then + WindowStyle := gtk_style_copy(gtk_widget_get_style(AWidget)) + else + WindowStyle := gtk_style_copy(gtk_rc_get_style(AWidget)); + + if (Windowstyle = nil) then + Windowstyle := gtk_style_new; - FontGdiObject:=PGdiObject(AFont.Handle); - windowstyle^.font:=pointer(FontGdiObject^.GdiFontObject); - gtk_widget_set_style(aWidget,windowStyle); + FontGdiObject := PGdiObject(AFont.Reference.Handle); + windowstyle^.font := Pointer(FontGdiObject^.GdiFontObject); + gtk_widget_set_style(aWidget, windowStyle); end; diff --git a/lcl/interfaces/gtk/gtkcallback.inc b/lcl/interfaces/gtk/gtkcallback.inc index 49d9bca3a4..19964ab0af 100644 --- a/lcl/interfaces/gtk/gtkcallback.inc +++ b/lcl/interfaces/gtk/gtkcallback.inc @@ -1827,651 +1827,6 @@ begin DeliverMessage(Data, Mess); end; -{------------------------------------------------------------------------------- - function GTKDialogSelectRowCB - Params: widget: PGtkWidget; data: gPointer - Result: GBoolean - - This function is called, whenever a row is selected in a commondialog --------------------------------------------------------------------------------} -function gtkDialogSelectRowCB(widget: PGtkWidget; Row, Column: gInt; - bevent: pgdkEventButton; data: gPointer): GBoolean; cdecl; -var - theDialog: TCommonDialog; - MenuWidget: PGtkWidget; - AFilterEntry: PFileSelFilterEntry; - FileSelWidget: PGtkFileSelection; - ShiftState: TShiftState; - loop : gint; - startRow : gint; - endRow : gint; -begin - //debugln('GTKDialogSelectRowCB A '); - Result:=CallBackDefaultReturn; - if (Data=nil) or (BEvent=nil) or (Column=0) or (Row=0) then ; - theDialog:=TCommonDialog(GetLCLObject(Widget)); - if (theDialog is TOpenDialog) then begin - // only process the callback if there is event data. If there isn't any - // event data that means it was called due to a direct function call of the - // widget and not an actual mouse click on the widget. - FileSelWidget:=PGtkFileSelection(theDialog.Handle); - if (bevent <> nil) and (gdk_event_get_type(bevent) = GDK_2BUTTON_PRESS) - and (FileSelWidget^.dir_list = widget) then begin - MenuWidget := gtk_object_get_data(PGtkObject(FileSelWidget), - 'LCLFilterMenu'); - if MenuWidget <> nil then begin - AFilterEntry := gtk_object_get_data(PGtkObject( - gtk_menu_get_active(PGtkMenu(MenuWidget))), 'LCLIsFilterMenuItem'); - if (AFilterEntry<>nil) and (AFilterEntry^.Mask<>nil) then - PopulateFileAndDirectoryLists(FileSelWidget,AFilterEntry^.Mask); - end; - end - else if (bevent <> nil) - and (ofAllowMultiSelect in TOpenDialog(theDialog).Options) - and (FileSelWidget^.file_list=widget) then begin - // multi selection - ShiftState := GTKEventStateToShiftState(BEvent^.State); - if ssShift in ShiftState then begin - if LastFileSelectRow <> -1 then begin - startRow := LastFileSelectRow; - endRow := row; - if LastFileSelectRow > row then begin - startRow := row; - endRow := LastFileSelectRow; - end; - for loop := startRow to endRow do begin - gtk_clist_select_row(PGtkCList(widget), loop, column); - end; - end; - end - else if not (ssCtrl in ShiftState) then begin - gtk_clist_unselect_all(PGtkCList(widget)); - gtk_clist_select_row(PGtkCList(widget), row, column); - end; - LastFileSelectRow := row; - end; - UpdateDetailView(TOpenDialog(theDialog)); - end; -end; - -function gtkDialogOKclickedCB( widget: PGtkWidget; - data: gPointer) : GBoolean; cdecl; -var - theDialog : TCommonDialog; - Fpointer : Pointer; - // colordialog - colorsel : PGtkColorSelection; - newColor : TGdkColor; - // fontdialog - FontName : String; - ALogFont : TLogFont; - // filedialog - rowNum : gint; - fileInfo : PGChar; - {$IfDef GTK2} - fileList : PPgchar; - FontDesc: PPangoFontDescription; - {$else} - cListRow : PGList; - fileList : PGTKCList; - {$EndIf} - DirName : string; - FileName : string; - Files: TStringList; - CurFilename: string; - //SelectedFont: PGdkFont; - - function CheckOpenedFilename(var AFilename: string): boolean; - {$IFDEF GTK1} - var - MenuWidget: PGtkWidget; - AFilterEntry: PFileSelFilterEntry; - {$ENDIF} - begin - Result:=true; - {$IFDEF GTK1} - // check if entered file are a real directory - if DirectoryExists(AFileName) then - begin - // if only interested in directories, then it's done - if TheDialog is TSelectDirectoryDialog then - begin - result := True; - exit; - end; - // if allowed then jump to that directory - if not (ofNoChangeDir in TOpenDialog(TheDialog).Options) then - begin - // change dir - gtk_file_selection_set_filename(PGtkFileSelection(FPointer), - PChar(AppendPathDelim(AFileName))); - - // populate file list - MenuWidget := gtk_object_get_data(PGtkObject(PGtkFileSelection(FPointer)), 'LCLFilterMenu'); - if (MenuWidget <> nil) then begin - AFilterEntry := gtk_object_get_data(PGtkObject(gtk_menu_get_active( - PGtkMenu(MenuWidget))), 'LCLIsFilterMenuItem'); - if ((AFilterEntry<>nil) and (AFilterEntry^.Mask<>nil)) then - PopulateFileAndDirectoryLists(PGtkFileSelection(FPointer), AFilterEntry^.Mask); - end; - end; - // wait for correct input - result:=False; - Exit; - end; - - // maybe user entered nonexistent dir - if ((AFileName<>'') and (IsPathDelimiter(AFileName, Length(AFileName)))) then - begin - // cant jump to nonexistent dir - if not (ofNoChangeDir in TOpenDialog(TheDialog).Options) then - MessageDlg(rsfdDirectoryMustExist, Format(rsfdDirectoryNotExist,[AFileName]), - mtError, [mbCancel], 0); // GTK2 shows "The folder contents could not be displayed" - // wait for correct input - result:=False; - Exit; - end; - - // check if user selected a file while requesting a directory - if (AFileName<>'') and (TheDialog is TSelectDirectoryDialog) then begin - if DirectoryExists(ExtractFilePath(AFileName)) then begin - AFileName:=ExtractFilePath(AFileName); - result:=true; - exit; - end; - end; - - {$ENDIF} - // maybe file already exists - if (ofOverwritePrompt in TOpenDialog(theDialog).Options) - and FileExists(AFilename) then - begin - Result:=MessageDlg(rsfdOverwriteFile, - Format(rsfdFileAlreadyExists,[AFileName]), - mtConfirmation,[mbOk,mbCancel],0)=mrOk; - if not Result then exit; - end; - end; - - procedure AddFile(List: TStrings; const NewFile: string); - var - i: Integer; - begin - for i:=0 to List.Count-1 do - if List[i]=NewFile then exit; - List.Add(NewFile); - end; - -begin - Result := True; - if (Widget=nil) then ; - theDialog := TCommonDialog(data); - FPointer := Pointer(theDialog.Handle); - - if theDialog is TFileDialog then - begin - {$IfDef GTK2} - FileName:=gtk_file_chooser_get_filename(PGtkFileChooser(FPointer)); - {$ELSE} - FileName:=gtk_file_selection_get_filename( - PGtkFileSelection(FPointer)); - {$ENDIF} - if theDialog is TOpenDialog then - begin - // check extra options - if ofAllowMultiSelect in TOpenDialog(theDialog).Options then - begin - DirName:=ExtractFilePath(FileName); - TFileDialog(data).FileName := ''; - Files:=TStringList(TFileDialog(theDialog).Files); - Files.Clear; - if (Filename<>'') then begin - Result:=CheckOpenedFilename(Filename); - if not Result then exit; - AddFile(Files,FileName); - end; - {$IfDef GTK2} - fileList := gtk_file_selection_get_selections(PGtkFileSelection(FPointer)); - rowNum := 0; - While FileList^ <> nil do - begin - fileInfo := FileList^; - CurFilename:=fileInfo; // convert PChar to AnsiString (not typecast) - if (CurFilename<>'') and (Files.IndexOf(CurFilename)<0) then begin - CurFilename:=DirName+fileInfo; - Result:=CheckOpenedFilename(CurFilename); - if not Result then exit; - Files.Add(CurFilename); - end; - inc(FileList); - inc(rowNum); - end; - Dec(FileList, rowNum); - g_strfreev(fileList); - {$Else} - fileList := PGtkCList(PGtkFileSelection(FPointer)^.file_list); - rowNum := 0; - cListRow := fileList^.row_list; - while cListRow <> nil do - begin - if PGtkCListRow(cListRow^.data)^.state = GTK_STATE_SELECTED then - begin - if gtk_clist_get_cell_type(fileList, rowNum, 0) = GTK_CELL_TEXT - then begin - gtk_clist_get_text(fileList, rowNum, 0, @fileInfo); - CurFilename:=DirName+fileInfo; - Result:=CheckOpenedFilename(CurFilename); - if not Result then exit; - AddFile(Files,CurFilename); - end; - end; - // get next row from list - rowNum := rowNum + 1; - cListRow := g_list_next(cListRow); - end; - {$EndIf} - end else begin - Result:=CheckOpenedFilename(Filename); - if not Result then exit; - TFileDialog(data).FileName := Filename; - end; - end - else - begin - TFileDialog(data).FileName := Filename; - end; - end - else if theDialog is TColorDialog then - begin - colorSel := PGtkColorSelection(PGtkColorSelectionDialog(FPointer)^.colorsel); - gtk_color_selection_get_current_color(colorsel, @newColor); - TColorDialog(theDialog).Color := TGDKColorToTColor(newcolor); - {$IFDEF VerboseColorDialog} - DebugLn('gtkDialogOKclickedCB ',DbgS(TColorDialog(theDialog).Color)); - {$ENDIF} - end - else if theDialog is TFontDialog then - begin - Assert(False, 'Trace:Pressed OK in FontDialog'); - FontName := gtk_font_selection_dialog_get_font_name( - pgtkfontselectiondialog(FPointer)); - //debugln('gtkDialogOKclickedCB FontName=',FontName); - //SelectedFont:=gdk_font_load(PChar(FontName)); - //debugln('gtkDialogOKclickedCB ',dbgs(SelectedFont)); - - if IsFontNameXLogicalFontDesc(FontName) then begin - // extract basic font attributes from the font name in XLFD format - ALogFont:=XLFDNameToLogFont(FontName); - TFontDialog(theDialog).Font.Assign(ALogFont); - // set the font name in XLFD format - // a font name in XLFD format overrides in the gtk interface all other font - // settings. - TFontDialog(theDialog).Font.Name := FontName; - end else begin - {$ifdef GTK2} - FontDesc := pango_font_description_from_string(PChar(FontName)); - with TFontDialog(theDialog).Font do - begin - BeginUpdate; - Size := pango_font_description_get_size(FontDesc) div PANGO_SCALE; - if pango_font_description_get_weight(FontDesc) >= PANGO_WEIGHT_BOLD then - Style := Style + [fsBold] - else - Style := Style - [fsBold]; - if pango_font_description_get_style(FontDesc) > PANGO_STYLE_NORMAL then - Style := Style + [fsItalic] - else - Style := Style - [fsItalic]; - Name := pango_font_description_get_family(FontDesc); - EndUpdate; - end; - pango_font_description_free(FontDesc); - {$else} - debugln('Gtk1 should have valid XLogicalFontDesc!'); - {$endif} - end; - - Assert(False, 'Trace:-----'+TFontDialog(theDialog).Font.Name+'----'); - end; - - StoreCommonDialogSetup(theDialog); - theDialog.UserChoice := mrOK; -end; - -{------------------------------------------------------------------------------- - function gtkDialogCancelclickedCB - Params: widget: PGtkWidget; data: gPointer - Result: GBoolean - - This function is called, whenever the user clicks the cancel button in a - commondialog --------------------------------------------------------------------------------} -function gtkDialogCancelclickedCB(widget: PGtkWidget; data: gPointer): GBoolean; - cdecl; -var - theDialog : TCommonDialog; -begin - Result := CallBackDefaultReturn; - if (Widget=nil) then ; - theDialog := TCommonDialog(data); - if theDialog is TFileDialog then - begin - TFileDialog(data).FileName := ''; - end; - StoreCommonDialogSetup(theDialog); - theDialog.UserChoice := mrCancel; -end; - -{------------------------------------------------------------------------------- - function gtkDialogHelpclickedCB - Params: widget: PGtkWidget; data: gPointer - Result: GBoolean - - This function is called, whenever the user clicks the help button in a - commondialog --------------------------------------------------------------------------------} -function gtkDialogHelpclickedCB(widget: PGtkWidget; data: gPointer): GBoolean; - cdecl; -var - theDialog : TCommonDialog; -begin - Result := CallBackDefaultReturn; - if (Widget=nil) then ; - theDialog := TCommonDialog(data); - if theDialog is TOpenDialog then begin - if TOpenDialog(theDialog).OnHelpClicked<>nil then - TOpenDialog(theDialog).OnHelpClicked(theDialog); - end; -end; - -{------------------------------------------------------------------------------- - function gtkDialogApplyclickedCB - Params: widget: PGtkWidget; data: gPointer - Result: GBoolean - - This function is called, whenever the user clicks the Apply button in a - commondialog --------------------------------------------------------------------------------} -function gtkDialogApplyclickedCB(widget: PGtkWidget; data: gPointer): GBoolean; - cdecl; -var - theDialog : TCommonDialog; - FontName: string; - ALogFont: TLogFont; - {$ifdef GTK2} - FontDesc: PPangoFontDescription; - {$endif} -begin - Result := CallBackDefaultReturn; - if (Widget=nil) then ; - theDialog := TCommonDialog(data); - if (theDialog is TFontDialog) - and (fdApplyButton in TFontDialog(theDialog).Options) - and (Assigned(TFontDialog(theDialog).OnApplyClicked)) then begin - FontName := gtk_font_selection_dialog_get_font_name( - pgtkfontselectiondialog(theDialog.Handle)); - if IsFontNameXLogicalFontDesc(FontName) then begin - // extract basic font attributes from the font name in XLFD format - ALogFont:=XLFDNameToLogFont(FontName); - TFontDialog(theDialog).Font.Assign(ALogFont); - // set the font name in XLFD format - // a font name in XLFD format overrides in the gtk interface all other font - // settings. - TFontDialog(theDialog).Font.Name := FontName; - end else begin - {$ifdef GTK2} - FontDesc := pango_font_description_from_string(PChar(FontName)); - with TFontDialog(theDialog).Font do - begin - BeginUpdate; - Size := pango_font_description_get_size(FontDesc) div PANGO_SCALE; - if pango_font_description_get_weight(FontDesc) >= PANGO_WEIGHT_BOLD then - Style := Style + [fsBold] - else - Style := Style - [fsBold]; - if pango_font_description_get_style(FontDesc) > PANGO_STYLE_NORMAL then - Style := Style + [fsItalic] - else - Style := Style - [fsItalic]; - Name := pango_font_description_get_family(FontDesc); - EndUpdate; - end; - pango_font_description_free(FontDesc); - {$else} - debugln('Gtk1 should have valid XLogicalFontDesc!'); - {$endif} - end; - TFontDialog(theDialog).OnApplyClicked(theDialog); - end; -end; - -{------------------------------------------------------------------------------- - function gtkDialogCloseQueryCB - Params: widget: PGtkWidget; data: gPointer - Result: GBoolean - - This function is called, before a commondialog is destroyed --------------------------------------------------------------------------------} -function gtkDialogCloseQueryCB(widget: PGtkWidget; data: gPointer): GBoolean; - cdecl; -var - theDialog : TCommonDialog; - CanClose: boolean; -begin - Result := False; // true = do nothing, false = destroy or hide window - if (Data=nil) then ; - // data is not the commondialog. Get it manually. - theDialog := TCommonDialog(GetLCLObject(Widget)); - if theDialog=nil then exit; - if theDialog.OnCanClose<>nil then begin - CanClose:=True; - theDialog.OnCanClose(theDialog,CanClose); - Result:=not CanClose; - end; - if not Result then begin - StoreCommonDialogSetup(theDialog); - DestroyCommonDialogAddOns(theDialog); - end; -end; - -{------------------------------------------------------------------------------- - procedure UpdateDetailView - Params: OpenDialog: TOpenDialog - Result: none - - Shows some OS dependent information about the current file --------------------------------------------------------------------------------} -procedure UpdateDetailView(OpenDialog: TOpenDialog); -var - FileDetailLabel: PGtkWidget; - Filename, OldFilename, Details: string; - Widget: PGtkWidget; -begin - //DebugLn(['UpdateDetailView ']); - Widget:=PGtkWidget(OpenDialog.Handle); - {$IfDef GTK2} - FileName:=gtk_file_chooser_get_filename(PGtkFileChooser(Widget)); - {$ELSE} - FileName:=gtk_file_selection_get_filename( - PGtkFileSelection(Widget)); - {$ENDIF} - OldFilename:=OpenDialog.Filename; - if Filename=OldFilename then exit; - OpenDialog.Filename:=Filename; - // tell application, that selection has changed - OpenDialog.DoSelectionChange; - if (OpenDialog.OnFolderChange<>nil) - and (ExtractFilePath(Filename)<>ExtractFilePath(OldFilename)) then - OpenDialog.DoFolderChange; - // show some information - FileDetailLabel:=gtk_object_get_data(PGtkObject(OpenDialog.Handle), - 'FileDetailLabel'); - if FileDetailLabel=nil then exit; - if FileExists(Filename) then begin - Details:=GetFileDescription(Filename); - end else begin - Details:=Format(rsFileInfoFileNotFound, [Filename]); - end; - gtk_label_set_text(PGtkLabel(FileDetailLabel),PChar(Details)); -end; - -{------------------------------------------------------------------------------- - function GTKDialogKeyUpDownCB - Params: Widget: PGtkWidget; Event : pgdkeventkey; Data: gPointer - Result: GBoolean - - This function is called, whenever a key is pressed or released in a common - dialog window --------------------------------------------------------------------------------} -function GTKDialogKeyUpDownCB(Widget: PGtkWidget; Event : pgdkeventkey; - Data: gPointer) : GBoolean; cdecl; -begin - //debugln('GTKDialogKeyUpDownCB A '); - Result:=CallBackDefaultReturn; - - if (Widget=nil) then ; - case gdk_event_get_type(Event) of - - GDK_KEY_RELEASE, GDK_KEY_PRESS: - begin - if Event^.KeyVal = GDK_KEY_Escape - then begin - StoreCommonDialogSetup(TCommonDialog(data)); - TCommonDialog(data).UserChoice:=mrCancel; - end; - if (TCommonDialog(data) is TOpenDialog) then begin - UpdateDetailView(TOpenDialog(data)); - end; - end; - - end; -end; - -{------------------------------------------------------------------------------- - function GTKDialogRealizeCB - Params: Widget: PGtkWidget; Data: Pointer - Result: GBoolean - - This function is called, whenever a commondialog window is realized --------------------------------------------------------------------------------} -function GTKDialogRealizeCB(Widget: PGtkWidget; Data: Pointer): GBoolean; cdecl; -var - LCLComponent: TObject; -begin - if (Data=nil) then ; - gdk_window_set_events(GetControlWindow(Widget), - gdk_window_get_events(GetControlWindow(Widget)) - or GDK_KEY_RELEASE_MASK or GDK_KEY_PRESS_MASK); - LCLComponent:=GetLCLObject(Widget); - if LCLComponent is TCommonDialog then - TCommonDialog(LCLComponent).DoShow; - Result:=true; -end; - -{------------------------------------------------------------------------------- - function GTKDialogFocusInCB - Params: widget: PGtkWidget; data: gPointer - Result: GBoolean - - This function is called, when a widget of a commondialog gets focus --------------------------------------------------------------------------------} -function GTKDialogFocusInCB(widget: PGtkWidget; data: gPointer): GBoolean; - cdecl; -var - theDialog: TCommonDialog; -begin - //debugln('GTKDialogFocusInCB A '); - Result:=CallBackDefaultReturn; - if (Data=nil) then ; - theDialog:=TCommonDialog(GetLCLObject(Widget)); - if (theDialog is TOpenDialog) then begin - UpdateDetailView(TOpenDialog(theDialog)); - end; -end; - -{------------------------------------------------------------------------------- - function GTKDialogMenuActivateCB - Params: widget: PGtkWidget; data: gPointer - Result: GBoolean - - This function is called, whenever a menu of a commondialog is activated --------------------------------------------------------------------------------} -function GTKDialogMenuActivateCB(widget: PGtkWidget; data: gPointer): GBoolean; - cdecl; -var - theDialog: TCommonDialog; - - procedure CheckFilterActivated(FilterWidget: PGtkWidget); - var - AFilterEntry: PFileSelFilterEntry; - begin - if FilterWidget=nil then exit; - AFilterEntry:=gtk_object_get_data(PGtkObject(FilterWidget), - 'LCLIsFilterMenuItem'); - if (AFilterEntry<>nil) and (AFilterEntry^.Mask<>nil) then - begin - PopulateFileAndDirectoryLists(PGtkFileSelection(theDialog.Handle), - AFilterEntry^.Mask); - TFileDialog(TheDialog).IntfFileTypeChanged(AFilterEntry^.FilterIndex + 1); - UpdateDetailView(TOpenDialog(theDialog)); - end; - end; - -var - AHistoryEntry: PFileSelHistoryEntry; - {$IFDEF Gtk1} - FilterMenu, ActiveFilterMenuItem: PGtkWidget; - {$ENDIF} -begin - Result:=false; - if (Data=nil) then ; - theDialog:=TCommonDialog(GetNearestLCLObject(Widget)); - if (theDialog is TOpenDialog) then begin - // check if history activated - AHistoryEntry:=gtk_object_get_data(PGtkObject(Widget), - 'LCLIsHistoryMenuItem'); - if (AHistoryEntry<>nil) and (AHistoryEntry^.Filename<>nil) then begin - // user has choosen a history file - // -> select it in the filedialog - {$IFDEF GTK1} - gtk_file_selection_complete(PGtkFileSelection(theDialog.Handle), - AHistoryEntry^.Filename); - // restore filter - if DirPathExists(AHistoryEntry^.Filename) then begin - FilterMenu:=gtk_object_get_data(PGtkObject(theDialog.Handle), - 'LCLFilterMenu'); - if FilterMenu<>nil then begin - ActiveFilterMenuItem:=gtk_menu_get_active(GTK_MENU(FilterMenu)); - CheckFilterActivated(ActiveFilterMenuItem); - end; - end; - {$ELSE} - gtk_file_chooser_set_current_folder(PGtkFileChooser(theDialog.Handle),AHistoryEntry^.Filename); - {$ENDIF} - UpdateDetailView(TOpenDialog(theDialog)); - end; - {$IFDEF GTK1} - // check if filter activated - CheckFilterActivated(Widget); - {$ENDIF} - end; -end; - -{------------------------------------------------------------------------------- - function gtkDialogDestroyCB - Params: widget: PGtkWidget; data: gPointer - Result: GBoolean - - This function is called, when a commondialog is destroyed --------------------------------------------------------------------------------} -function gtkDialogDestroyCB(widget: PGtkWidget; data: gPointer): GBoolean; cdecl; -begin - Result := True; - if (Widget=nil) then ; - TCommonDialog(data).UserChoice := mrAbort; - TCommonDialog(data).Close; -end; - function gtkPressedCB( widget: PGtkWidget; data: gPointer) : GBoolean; cdecl; var Mess : TLMessage; diff --git a/lcl/interfaces/gtk/gtkint.pp b/lcl/interfaces/gtk/gtkint.pp index cdd3e7cb7d..442183485a 100644 --- a/lcl/interfaces/gtk/gtkint.pp +++ b/lcl/interfaces/gtk/gtkint.pp @@ -146,8 +146,6 @@ type Function GetCompStyle(Sender : TObject) : Longint; Virtual; // create and destroy - function CreateComponentWidget(Sender: TObject; ACompStyle: Integer; const ACaption: String - ): PGtkWidget; virtual; // temporary solution till all are created through createhandle function CreateAPIWidget(AWinControl: TWinControl): PGtkWidget; function OldCreateStatusBarPanel(StatusBar: TObject; Index: integer): PGtkWidget; function CreateSimpleClientAreaWidget(Sender: TObject; @@ -213,18 +211,6 @@ type // forms and dialogs procedure BringFormToFront(Sender: TObject); procedure UntransientWindow(GtkWindow: PGtkWindow); - procedure InitializeFileDialog(FileDialog: TFileDialog; - var SelWidget: PGtkWidget; Title: PChar); virtual; - procedure InitializeFontDialog(FontDialog: TFontDialog; - var SelWidget: PGtkWidget; Title: PChar); - procedure InitializeCommonDialog(ADialog: TObject; AWindow: PGtkWidget); - function CreateOpenDialogFilter(OpenDialog: TOpenDialog; - SelWidget: PGtkWidget): string; virtual; - procedure CreatePreviewDialogControl(PreviewDialog: TPreviewFileDialog; - SelWidget: PGtkWidget); virtual; - procedure InitializeOpenDialog(OpenDialog: TOpenDialog; - SelWidget: PGtkWidget); virtual; - // misc function GetCaption(Sender : TObject) : String; virtual; procedure WordWrap(DC: HDC; AText: PChar; MaxWidthInPixel: integer; @@ -293,7 +279,6 @@ type ConvertAmpersandsToUnderScores: Boolean) : PChar; // create and destroy - function CreateComponent(Sender: TObject): THandle; override; function CreateTimer(Interval: integer; TimerFunc: TFNTimerProc) : THandle; override; function DestroyTimer(TimerHandle: THandle) : boolean; override; procedure DestroyLCLComponent(Sender: TObject);virtual; @@ -308,9 +293,6 @@ type {$I gtklistslh.inc} {$I gtkfiledialogutilsh.inc} -procedure CreateOpenDialogHistory(OpenDialog: TOpenDialog; - SelWidget: PGtkWidget); - var GTKWidgetSet: TGTKWidgetSet; @@ -328,7 +310,7 @@ uses GtkWSButtons, GtkWSCalendar, GtkWSCheckLst, -// GtkWSCListBox, + GtkWSCListBox, GtkWSComCtrls, GtkWSControls, // GtkWSDbCtrls, diff --git a/lcl/interfaces/gtk/gtkproc.pp b/lcl/interfaces/gtk/gtkproc.pp index 39a749512c..d42792819e 100644 --- a/lcl/interfaces/gtk/gtkproc.pp +++ b/lcl/interfaces/gtk/gtkproc.pp @@ -177,22 +177,6 @@ function gtkMouseBtnReleaseAfter(widget: PGtkWidget; event: pgdkEventButton; data: gPointer): GBoolean; cdecl; function gtkclickedCB( widget: PGtkWidget; data: gPointer): GBoolean; cdecl; -function gtkDialogSelectRowCB(widget: PGtkWidget; Row, Column: gInt; - bevent: pgdkEventButton; data: gPointer): GBoolean; cdecl; -function gtkDialogOKclickedCB( widget: PGtkWidget; - data: gPointer): GBoolean; cdecl; -function gtkDialogCancelclickedCB(widget: PGtkWidget; data: gPointer): GBoolean;cdecl; -function gtkDialogHelpclickedCB(widget: PGtkWidget; data: gPointer): GBoolean;cdecl; -function gtkDialogApplyclickedCB(widget: PGtkWidget; data: gPointer): GBoolean; cdecl; -function gtkDialogCloseQueryCB(widget: PGtkWidget; data: gPointer): GBoolean; cdecl; -procedure UpdateDetailView(OpenDialog: TOpenDialog); -function GTKDialogKeyUpDownCB(Widget: PGtkWidget; Event: pgdkeventkey; - Data: gPointer): GBoolean; cdecl; -function GTKDialogRealizeCB(Widget: PGtkWidget; Data: Pointer): GBoolean; cdecl; -function GTKDialogFocusInCB(widget: PGtkWidget; data: gPointer): GBoolean; cdecl; -function GTKDialogMenuActivateCB(widget: PGtkWidget; data: gPointer): GBoolean; cdecl; -function gtkDialogDestroyCB(widget: PGtkWidget; data: gPointer): GBoolean; cdecl; - function gtkPressedCB( widget: PGtkWidget; data: gPointer): GBoolean; cdecl; function gtkEnterCB(widget: PGtkWidget; data: gPointer): GBoolean; cdecl; function gtkLeaveCB(widget: PGtkWidget; data: gPointer): GBoolean; cdecl; diff --git a/lcl/interfaces/gtk/gtkwidgetset.inc b/lcl/interfaces/gtk/gtkwidgetset.inc index 3d08ca25fc..cd74e0bee0 100644 --- a/lcl/interfaces/gtk/gtkwidgetset.inc +++ b/lcl/interfaces/gtk/gtkwidgetset.inc @@ -3984,474 +3984,6 @@ begin end; end; -{------------------------------------------------------------------------------ - procedure TGtkWidgetSet.InitializeCommonDialog - Params: ADialog: TCommonDialog; AWindow: PGtkWidget - Result: none - - Initializes a TCommonDialog window. -------------------------------------------------------------------------------} -procedure TGtkWidgetSet.InitializeCommonDialog(ADialog: TObject; - AWindow: PGtkWidget); -var NewWidth, NewHeight: integer; -begin - SetLCLObject(AWindow,ADialog); - - // connect events - g_signal_connect(gtk_object(AWindow), - 'destroy', gtk_Signal_Func(@gtkDialogDestroyCB), ADialog); - g_signal_connect(gtk_object(AWindow), - 'delete-event', gtk_Signal_Func(@gtkDialogCloseQueryCB), ADialog); - g_signal_connect(gtk_object(AWindow), - 'key-press-event', gtk_Signal_Func(@GTKDialogKeyUpDownCB), ADialog); - g_signal_connect(gtk_object(AWindow), - 'key-release-event', gtk_Signal_Func(@GTKDialogKeyUpDownCB), ADialog); - g_signal_connect(gtk_object(AWindow), - 'realize', gtk_Signal_Func(@GTKDialogRealizeCB), ADialog); - - // set default size - NewWidth:=TCommonDialog(ADialog).Width; - if NewWidth<=0 then NewWidth:=-2; // -2 = let the window manager decide - NewHeight:=TCommonDialog(ADialog).Height; - if NewHeight<=0 then NewHeight:=-2; // -2 = let the window manager decide - if (NewWidth>0) or (NewHeight>0) then - gtk_window_set_default_size(PgtkWindow(AWindow),NewWidth,NewHeight); -end; - -{------------------------------------------------------------------------------ - Function: CreateOpenDialogHistory - Params: OpenDialog: TOpenDialog; SelWidget: PGtkWidget - Returns: - - - Adds a History pulldown to a gtk file selection dialog. - ------------------------------------------------------------------------------} -procedure CreateOpenDialogHistory(OpenDialog: TOpenDialog; - SelWidget: PGtkWidget); -var - HistoryList: TFPList; // list of THistoryListEntry - AHistoryEntry: PFileSelHistoryEntry; - i: integer; - s: string; - HBox, LabelWidget, HistoryPullDownWidget, - MenuWidget, MenuItemWidget: PGtkWidget; -begin - if OpenDialog.HistoryList.Count>0 then begin - - // create the HistoryList where the current state of the history is stored - HistoryList:=TFPList.Create; - for i:=0 to OpenDialog.HistoryList.Count-1 do begin - s:=OpenDialog.HistoryList[i]; - if s<>'' then begin - New(AHistoryEntry); - HistoryList.Add(AHistoryEntry); - AHistoryEntry^.Filename := StrAlloc(length(s)+1); - StrPCopy(AHistoryEntry^.Filename, s); - AHistoryEntry^.MenuItem:=nil; - end; - end; - - // create a HBox so that the history is left justified - HBox:=gtk_hbox_new(false,0); - gtk_object_set_data(PGtkObject(SelWidget), 'LCLHistoryHBox', HBox); - {$IFDEF GTK1} - gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(SelWidget)^.main_vbox), - HBox,false,false,0); - {$ELSE} - gtk_file_chooser_set_extra_widget(PGtkDialog(SelWidget),HBox); - {$ENDIF} - - // create the label 'History:' - s:=rsgtkHistory; - LabelWidget:=gtk_label_new(PChar(s)); - gtk_box_pack_start(GTK_BOX(HBox),LabelWidget,false,false,5); - gtk_widget_show(LabelWidget); - - // create the pull down - HistoryPullDownWidget:=gtk_option_menu_new; - gtk_object_set_data(PGtkObject(SelWidget), 'LCLHistoryPullDown', - HistoryPullDownWidget); - gtk_box_pack_start(GTK_BOX(HBox),HistoryPullDownWidget,false,false,5); - gtk_widget_show(HistoryPullDownWidget); - gtk_widget_show_all(HBox); - - // create the menu (the content of the pull down) - MenuWidget:=gtk_menu_new; - SetLCLObject(MenuWidget,OpenDialog); - for i:=0 to HistoryList.Count-1 do begin - // create the menu items in the history menu - MenuItemWidget:=gtk_menu_item_new_with_label( - PFileSelHistoryEntry(HistoryList[i])^.Filename); - // connect the new MenuItem to the HistoryList entry - gtk_object_set_data(PGtkObject(MenuItemWidget), 'LCLIsHistoryMenuItem', - HistoryList[i]); - // add activation signal and add to menu - g_signal_connect(GTK_OBJECT(MenuItemWidget), 'activate', - gtk_signal_func(@GTKDialogMenuActivateCB), - OpenDialog); - gtk_menu_append(MenuWidget, MenuItemWidget); - gtk_widget_show(MenuItemWidget); - end; - gtk_widget_show(MenuWidget); - gtk_option_menu_set_menu(GTK_OPTION_MENU(HistoryPullDownWidget), - MenuWidget); - end else begin - MenuWidget:=nil; - HistoryList:=nil - end; - gtk_object_set_data(PGtkObject(SelWidget), 'LCLHistoryMenu', MenuWidget); - gtk_object_set_data(PGtkObject(SelWidget), 'LCLHistoryList', HistoryList); -end; - -{------------------------------------------------------------------------------ - Function: TGtkWidgetSet.CreateOpenDialogFilter - Params: OpenDialog: TOpenDialog; SelWidget: PGtkWidget - Returns: - - - Adds a Filter pulldown to a gtk file selection dialog. Returns the - inital filter mask. - ------------------------------------------------------------------------------} -function TGtkWidgetSet.CreateOpenDialogFilter(OpenDialog: TOpenDialog; - SelWidget: PGtkWidget): string; -var - FilterList: TFPList; - HBox, LabelWidget, FilterPullDownWidget, - MenuWidget, MenuItemWidget: PGtkWidget; - i, j, CurMask: integer; - s: String; -begin - ExtractFilterList(OpenDialog.Filter,FilterList,false); - if FilterList.Count>0 then begin - - // create a HBox so that the filter pulldown is left justified - HBox:=gtk_hbox_new(false,0); - gtk_object_set_data(PGtkObject(SelWidget), 'LCLFilterHBox', HBox); - gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(SelWidget)^.main_vbox), - HBox,false,false,0); - - // create the label 'Filter:' - s:=rsgtkFilter; - LabelWidget:=gtk_label_new(PChar(s)); - gtk_box_pack_start(GTK_BOX(HBox),LabelWidget,false,false,5); - gtk_widget_show(LabelWidget); - - // create the pull down - FilterPullDownWidget:=gtk_option_menu_new; - gtk_object_set_data(PGtkObject(SelWidget), 'LCLFilterPullDown', - FilterPullDownWidget); - gtk_box_pack_start(GTK_BOX(HBox),FilterPullDownWidget,false,false,5); - gtk_widget_show(FilterPullDownWidget); - gtk_widget_show(HBox); - - // create the menu (the content of the pull down) - MenuWidget:=gtk_menu_new; - SetLCLObject(MenuWidget,OpenDialog); - for i:=0 to FilterList.Count-1 do begin - // create the menu items in the filter menu - MenuItemWidget:=gtk_menu_item_new_with_label( - PFileSelFilterEntry(FilterList[i])^.Description); - // connect the new MenuItem to the FilterList entry - gtk_object_set_data(PGtkObject(MenuItemWidget), 'LCLIsFilterMenuItem', - FilterList[i]); - // add activation signal and add to menu - g_signal_connect(GTK_OBJECT(MenuItemWidget), 'activate', - gtk_signal_func(@GTKDialogMenuActivateCB), - OpenDialog); - gtk_menu_append(MenuWidget, MenuItemWidget); - gtk_widget_show(MenuItemWidget); - end; - gtk_widget_show(MenuWidget); - gtk_option_menu_set_menu(GTK_OPTION_MENU(FilterPullDownWidget), - MenuWidget); - end else begin - MenuWidget:=nil; - end; - gtk_object_set_data(PGtkObject(SelWidget), 'LCLFilterMenu', MenuWidget); - gtk_object_set_data(PGtkObject(SelWidget), 'LCLFilterList', FilterList); - - // set the initial filter - Result := 'none'; { Don't use '' as null return as this is used for *.* } - if FilterList.Count>0 then begin - i:=0; - j:=OpenDialog.FilterIndex - 1; // FilterIndex is 1 based - if j<0 then j:=0; - CurMask:=0; - while (inil) then begin - gtk_widget_show(FileSelWidget^.Help_Button); - g_signal_connect( gtk_object(FileSelWidget^.help_button), - 'clicked', gtk_signal_func(@gtkDialogHelpclickedCB), OpenDialog); - end; - - // connect selection entry (edit field for filename) - if (FileSelWidget^.selection_entry<>nil) then begin - SetLCLObject(FileSelWidget^.selection_entry,OpenDialog); - g_signal_connect( - gtk_object(FileSelWidget^.selection_entry), - 'key-press-event', gtk_signal_func(@GTKDialogKeyUpDownCB), - OpenDialog); - g_signal_connect( - gtk_object(FileSelWidget^.selection_entry), - 'focus-in-event', gtk_signal_func(@GTKDialogFocusInCB), OpenDialog); - end; - - // connect dir list (list of directories) - if (FileSelWidget^.dir_list<>nil) then begin - SetLCLObject(FileSelWidget^.dir_list,OpenDialog); - g_signal_connect(gtk_object(FileSelWidget^.dir_list), - 'select-row', gtk_signal_func(@GTKDialogSelectRowCB), OpenDialog); - end; - - // connect file list (list of files in current directory) - if (FileSelWidget^.file_list<>nil) then begin - LastFileSelectRow := -1; - SetLCLObject(FileSelWidget^.file_list,OpenDialog); - g_signal_connect(gtk_object(FileSelWidget^.file_list), - 'select-row', gtk_signal_func(@GTKDialogSelectRowCB), OpenDialog); - if ofAllowMultiSelect in OpenDialog.Options then - gtk_clist_set_selection_mode( - PGtkCList(FileSelWidget^.file_list),GTK_SELECTION_MULTIPLE); - end; - - // History List - a frame with an option menu - CreateOpenDialogHistory(OpenDialog,SelWidget); - - // Filter - a frame with an option menu - InitialFilter := CreateOpenDialogFilter(OpenDialog,SelWidget); - - // Details - a frame with a label - if (ofViewDetail in OpenDialog.Options) then begin - // create the frame around the information - FrameWidget:=gtk_frame_new(PChar(rsFileInformation)); - gtk_box_pack_start(GTK_BOX(FileSelWidget^.main_vbox), - FrameWidget,false,false,0); - gtk_widget_show(FrameWidget); - // create a HBox, so that the information is left justified - HBox:=gtk_hbox_new(false,0); - gtk_container_add(GTK_CONTAINER(FrameWidget), HBox); - // create the label for the file information - FileDetailLabel:=gtk_label_new(PChar(rsDefaultFileInfoValue)); - gtk_box_pack_start(GTK_BOX(HBox),FileDetailLabel,false,false,5); - gtk_widget_show_all(HBox); - end else - FileDetailLabel:=nil; - gtk_object_set_data(PGtkObject(SelWidget), 'FileDetailLabel', - FileDetailLabel); - - // preview - if (OpenDialog is TPreviewFileDialog) then - CreatePreviewDialogControl(TPreviewFileDialog(OpenDialog),SelWidget); - - // set initial filename - if OpenDialog.Filename<>'' then - gtk_file_selection_set_filename(FileSelWidget,PChar(OpenDialog.Filename)); - - if InitialFilter <> 'none' then - PopulateFileAndDirectoryLists(FileSelWidget, InitialFilter); -end; - -{------------------------------------------------------------------------------ - Function: TGtkWidgetSet.InitializeFileDialog - Params: FileDialog: TFileDialog; var SelWidget: PGtkWidget - Returns: - - - Creates a new TFile/Open/SaveDialog - ------------------------------------------------------------------------------} -procedure TGtkWidgetSet.InitializeFileDialog(FileDialog: TFileDialog; - var SelWidget: PGtkWidget; Title: PChar); -begin - //DebugLn(['TGtkWidgetSet.InitializeFileDialog ']); - SelWidget := gtk_file_selection_new(Title); - - {****This is a major hack put by Cliff Baeseman to solve - a gtk win32 dll implementation problem where the headers implementation - does not match the linux version**** } - {$IFNDEF WIN32} - g_signal_connect(gtk_object(PGtkFileSelection(SelWidget)^.ok_button), - 'clicked', gtk_signal_func(@gtkDialogOKclickedCB), FileDialog); - g_signal_connect(gtk_object(PGtkFileSelection(SelWidget)^.cancel_button), - 'clicked', gtk_signal_func(@gtkDialogCancelclickedCB), FileDialog); - {$ELSE} - g_signal_connect(gtk_object(PGtkFileSelection(SelWidget)^.cancel_button), - 'clicked', gtk_signal_func(@gtkDialogOKclickedCB), FileDialog); - g_signal_connect(gtk_object(PGtkFileSelection(SelWidget)^.help_button), - 'clicked', gtk_signal_func(@gtkDialogCancelclickedCB), FileDialog); - {$ENDIF} - - if FileDialog is TOpenDialog then - InitializeOpenDialog(TOpenDialog(FileDialog),SelWidget); - - InitializeCommonDialog(TCommonDialog(FileDialog),SelWidget); -end; - -{------------------------------------------------------------------------------ - Function: TGtkWidgetSet.InitializeFontDialog - Params: FontDialog: TFontialog; var SelWidget: PGtkWidget - Returns: - - - Creates a new TFontDialog - ------------------------------------------------------------------------------} -procedure TGtkWidgetSet.InitializeFontDialog(FontDialog: TFontDialog; - var SelWidget: PGtkWidget; Title: PChar); -{$IFDEF GTK1} -var - SpacingFilter: PPgchar; - FontType: TGtkFontType; -const - FixedFilter: array [0..2] of PChar = ( 'c', 'm', nil ); -{$ELSE} -var - FontDesc: PPangoFontDescription; - TmpStr: pChar; -{$ENDIF} -begin - SelWidget := gtk_font_selection_dialog_new(Title); - - // connect Ok, Cancel and Apply Button - g_signal_connect( - gtk_object(PGtkFontSelectionDialog(SelWidget)^.ok_button), - 'clicked', gtk_signal_func(@gtkDialogOKclickedCB), FontDialog); - g_signal_connect( - gtk_object(PGtkFontSelectionDialog(SelWidget)^.cancel_button), - 'clicked', gtk_signal_func(@gtkDialogCancelclickedCB), FontDialog); - g_signal_connect( - gtk_object(PGtkFontSelectionDialog(SelWidget)^.apply_button), - 'clicked', gtk_signal_func(@gtkDialogApplyclickedCB), FontDialog); - if fdApplyButton in FontDialog.Options then - gtk_widget_show(PGtkFontSelectionDialog(SelWidget)^.apply_button); - - // set preview text - if FontDialog.PreviewText<>'' then - gtk_font_selection_dialog_set_preview_text( - PGtkFontSelectionDialog(SelWidget),PChar(FontDialog.PreviewText)); - - // set font name in XLFD format - if IsFontNameXLogicalFontDesc(FontDialog.Font.Name) then - gtk_font_selection_dialog_set_font_name(PGtkFontSelectionDialog(SelWidget), - PChar(FontDialog.Font.Name)) - else begin - {$ifdef GTK2} - FontDesc := pango_font_description_new; - with FontDialog.Font do begin - pango_font_description_set_size(FontDesc, Size * PANGO_SCALE); - - if fsBold in Style then - pango_font_description_set_weight(FontDesc, PANGO_WEIGHT_BOLD) - else - pango_font_description_set_weight(FontDesc, PANGO_WEIGHT_NORMAL); - - if fsItalic in Style then - pango_font_description_set_style(FontDesc, PANGO_STYLE_ITALIC) - else - pango_font_description_set_style(FontDesc, PANGO_STYLE_NORMAL); - - pango_font_description_set_family(FontDesc, pChar(Name)); - end; - TmpStr := pango_font_description_to_string(FontDesc); - gtk_font_selection_dialog_set_font_name(PGtkFontSelectionDialog(SelWidget), TmpStr); - g_free(TmpStr); - pango_font_description_free(FontDesc); - {$else} - debugln('Gtk1 should have IsFontNameXLogicalFontDesc true!'); - {$endif} - end; - - {$IFDEF GTK1} - { This functionality does not seem to be available in GTK2 } - // Honor selected TFontDialogOption flags - SpacingFilter := nil; - if fdFixedPitchOnly in FontDialog.Options then - SpacingFilter := @FixedFilter[0]; - FontType := GTK_FONT_ALL; - if fdScalableOnly in FontDialog.Options then - FontType := GTK_FONT_SCALABLE; - gtk_font_selection_dialog_set_filter (PGtkFontSelectionDialog(SelWidget), - GTK_FONT_FILTER_BASE, FontType, - nil, nil, nil, nil, SpacingFilter, nil); - {$ENDIF} - - InitializeCommonDialog(TCommonDialog(FontDialog),SelWidget); -end; - - procedure TGtkWidgetSet.FinishComponentCreate(const ALCLObject: TObject; const AGTKObject: Pointer); begin // MWE: next will be obsoleted by WinWidgetInfo @@ -4682,76 +4214,6 @@ begin gtk_widget_show(Result); end; - -{------------------------------------------------------------------------------ - Function: TGtkWidgetSet.CreateComponentWidget - Params: Ssender - object for which to create visual representation - CompStyle - componentstyle (type) of GtkWidget which will be created - Caption - the caption of "Sender" - Returns: nothing - - Tells GTK Engine to create a widget - ------------------------------------------------------------------------------} -function TGTKWidgetSet.CreateComponentWidget(Sender: TObject; ACompStyle: Integer; const ACaption: String): PGtkWidget; -var - p: Pointer absolute Result; -begin - Result := nil; - - case ACompStyle of - csColorDialog : - begin - P := gtk_color_selection_dialog_new(PChar(ACaption)); - g_signal_connect( gtk_object((GTK_COLOR_SELECTION_DIALOG(P))^.ok_button), - 'clicked', gtk_signal_func(@gtkDialogOKclickedCB), Sender); - g_signal_connect( gtk_object((GTK_COLOR_SELECTION_DIALOG(P))^.cancel_button), - 'clicked', gtk_signal_func(@gtkDialogCancelclickedCB), Sender); - InitializeCommonDialog(TCommonDialog(Sender),p); - end; - - csFileDialog, csOpenFileDialog, csSaveFileDialog, csSelectDirectoryDialog, - csPreviewFileDialog: - InitializeFileDialog(TFileDialog(Sender),p,PChar(ACaption)); - - csFontDialog : - InitializeFontDialog(TFontDialog(Sender),p,PChar(ACaption)); - - csWinControl: // code moved for TCustomControl - p:=CreateAPIWidget(TWinControl(Sender)); - - csPreviewFileControl: - P:=CreateSimpleClientAreaWidget(Sender,true); - else - DebugLn('[WARNING] Obsolete call to TGTKOBject.CreateComponent for ', Sender.ClassName); - end; //end case -end; - - -{------------------------------------------------------------------------------ - Function: TGtkWidgetSet.CreateComponent - Params: sender - object for which to create visual representation - Returns: nothing - - Tells GTK Engine to create a widget - ------------------------------------------------------------------------------} -function TGtkWidgetSet.CreateComponent(Sender : TObject): THandle; -var - Caption: string; // the caption of "Sender" - p: pointer; // ptr to the newly created GtkWidget - CompStyle: Integer; // componentstyle (type) of GtkWidget which will be created -begin - CompStyle := GetCompStyle(Sender); - Caption := GetCaption(Sender); - - p := CreateComponentWidget(Sender, CompStyle, Caption); - - FinishComponentCreate(Sender, P); - {$IFDEF DebugLCLComponents} - DebugGtkWidgets.MarkCreated(P,dbgsName(Sender)); - {$ENDIF} - Result := THandle(PtrUInt(P)); -end; - {------------------------------------------------------------------------------ procedure TGtkWidgetSet.DestroyEmptySubmenu(Sender: TObject); diff --git a/lcl/interfaces/gtk/gtkwsclistbox.pp b/lcl/interfaces/gtk/gtkwsclistbox.pp index 1b402d44b3..d2538c7b08 100644 --- a/lcl/interfaces/gtk/gtkwsclistbox.pp +++ b/lcl/interfaces/gtk/gtkwsclistbox.pp @@ -27,7 +27,12 @@ unit GtkWSCListBox; interface uses - CListBox, WSCListBox, WSLCLClasses; + {$ifdef gtk1} + Gtk, gdk, Glib, + {$endif} + Classes, Math, Controls, CListBox, LCLType, LMessages, + InterfaceBase, WSCListBox, WSLCLClasses, + GtkInt, GtkDef, GtkProc, GtkWSControls; type @@ -37,11 +42,64 @@ type private protected public + {$IFDEF GTK1} + class procedure SetCallbacks(const AGtkWidget: PGtkWidget; const AWidgetInfo: PWidgetInfo); virtual; + class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override; + {$ENDIF} end; implementation +{ TGtkWSCListBox } + +{$IFDEF GTK1} +class procedure TGtkWSCListBox.SetCallbacks(const AGtkWidget: PGtkWidget; + const AWidgetInfo: PWidgetInfo); +begin + TGtkWSWinControl.SetCallbacks(PGtkObject(AGtkWidget), TComponent(AWidgetInfo^.LCLObject)); + TGtkWidgetset(Widgetset).SetCallback(LM_SELCHANGE, PGtkObject(AGtkWidget), AWidgetInfo^.LCLObject); +end; + +class function TGtkWSCListBox.CreateHandle(const AWinControl: TWinControl; + const AParams: TCreateParams): TLCLIntfHandle; +var + Widget: PGtkWidget; + WidgetInfo: PWidgetInfo; + ScrolledWnd: PGtkScrolledWindow absolute Widget; + CListBox: TCListBox absolute AWinControl; + + CList: Pointer; + n: Integer; +begin + Widget := gtk_scrolled_window_new(nil, nil); + GTK_WIDGET_UNSET_FLAGS(ScrolledWnd^.hscrollbar, GTK_CAN_FOCUS); + GTK_WIDGET_UNSET_FLAGS(ScrolledWnd^.vscrollbar, GTK_CAN_FOCUS); + gtk_scrolled_window_set_policy(ScrolledWnd, + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_widget_show(Widget); + + CList := gtk_clist_new(CListBox.ListColumns); + for n := 0 to CListBox.ListColumns - 1 do + gtk_clist_set_column_width(CList, n, (Max(0, CListBox.Width-10)) div CListBox.ListColumns); + + gtk_scrolled_window_add_with_viewport(ScrolledWnd, CList); + gtk_container_set_focus_vadjustment(CList, + gtk_scrolled_window_get_vadjustment(ScrolledWnd)); + gtk_container_set_focus_hadjustment(Clist, + gtk_scrolled_window_get_hadjustment(ScrolledWnd)); + gtk_widget_show(CList); + + WidgetInfo := CreateWidgetInfo(Widget, AWinControl, AParams); + SetMainWidget(Widget, CList); + WidgetInfo^.CoreWidget := CList; + TGtkWidgetSet(WidgetSet).SetSelectionMode(AWinControl, Widget, + CListBox.MultiSelect, CListBox.ExtendedSelect); + SetCallbacks(Widget, WidgetInfo); +end; +{$ENDIF} + initialization //////////////////////////////////////////////////// @@ -50,6 +108,6 @@ initialization // To improve speed, register only classes // which actually implement something //////////////////////////////////////////////////// -// RegisterWSComponent(TCListBox, TGtkWSCListBox); + RegisterWSComponent(TCListBox, TGtkWSCListBox); //////////////////////////////////////////////////// -end. \ No newline at end of file +end. diff --git a/lcl/interfaces/gtk/gtkwsdialogs.pp b/lcl/interfaces/gtk/gtkwsdialogs.pp index 0f682eacfb..4b6247c3b0 100644 --- a/lcl/interfaces/gtk/gtkwsdialogs.pp +++ b/lcl/interfaces/gtk/gtkwsdialogs.pp @@ -28,13 +28,15 @@ interface uses {$ifdef gtk2} - Gtk2, Glib2, gdk2, + Gtk2, Glib2, gdk2, pango, {$else} Gtk, gdk, Glib, {$endif} - SysUtils, Classes, Controls, LMessages, InterfaceBase, graphics, - LCLType, Dialogs, WSDialogs, WSLCLClasses, - gtkint, gtkproc, gtkwscontrols, gtkExtra; + SysUtils, Classes, + Controls, Graphics, Dialogs, ExtDlgs, + LCLType, LMessages, InterfaceBase, LCLStrConsts, LCLProc, FileUtil, + WSDialogs, WSLCLClasses, + GtkInt, GtkProc, GtkWSControls, GtkExtra, GtkDef, GtkGlobals; type @@ -44,6 +46,9 @@ type private protected public + class procedure SetCallbacks(const AGtkWidget: PGtkWidget; const AWidgetInfo: PWidgetInfo); virtual; + class procedure SetSizes(const AGtkWidget: PGtkWidget; const AWidgetInfo: PWidgetInfo); virtual; + class function CreateHandle(const ACommonDialog: TCommonDialog): THandle; override; class procedure ShowModal(const ACommonDialog: TCommonDialog); override; class procedure DestroyHandle(const ACommonDialog: TCommonDialog); override; @@ -54,7 +59,9 @@ type TGtkWSFileDialog = class(TWSFileDialog) private protected + class procedure SetCallbacks(const AGtkWidget: PGtkWidget; const AWidgetInfo: PWidgetInfo); virtual; public + class function CreateHandle(const ACommonDialog: TCommonDialog): THandle; override; end; { TGtkWSOpenDialog } @@ -62,7 +69,11 @@ type TGtkWSOpenDialog = class(TWSOpenDialog) private protected + class function CreateOpenDialogFilter(OpenDialog: TOpenDialog; SelWidget: PGtkWidget): string; virtual; + class procedure CreateOpenDialogHistory(OpenDialog: TOpenDialog; SelWidget: PGtkWidget); virtual; + class procedure CreatePreviewDialogControl(PreviewDialog: TPreviewFileDialog; SelWidget: PGtkWidget); virtual; public + class function CreateHandle(const ACommonDialog: TCommonDialog): THandle; override; end; { TGtkWSSaveDialog } @@ -86,7 +97,10 @@ type TGtkWSColorDialog = class(TWSColorDialog) private protected + protected + class procedure SetCallbacks(const AGtkWidget: PGtkWidget; const AWidgetInfo: PWidgetInfo); virtual; public + class function CreateHandle(const ACommonDialog: TCommonDialog): THandle; override; end; { TGtkWSColorButton } @@ -102,12 +116,664 @@ type TGtkWSFontDialog = class(TWSFontDialog) private protected + class procedure SetCallbacks(const AGtkWidget: PGtkWidget; const AWidgetInfo: PWidgetInfo); virtual; public + class function CreateHandle(const ACommonDialog: TCommonDialog): THandle; override; end; +// forward declarations + +procedure UpdateDetailView(OpenDialog: TOpenDialog); +function gtkDialogHelpclickedCB(widget: PGtkWidget; data: gPointer): GBoolean; cdecl; implementation - + +{------------------------------------------------------------------------------- + procedure UpdateDetailView + Params: OpenDialog: TOpenDialog + Result: none + + Shows some OS dependent information about the current file +-------------------------------------------------------------------------------} +procedure UpdateDetailView(OpenDialog: TOpenDialog); +var + FileDetailLabel: PGtkWidget; + Filename, OldFilename, Details: String; + Widget: PGtkWidget; +begin + //DebugLn(['UpdateDetailView ']); + Widget := PGtkWidget(OpenDialog.Handle); + {$IfDef GTK2} + FileName := gtk_file_chooser_get_filename(PGtkFileChooser(Widget)); + {$ELSE} + FileName := gtk_file_selection_get_filename(PGtkFileSelection(Widget)); + {$ENDIF} + OldFilename := OpenDialog.Filename; + if Filename = OldFilename then + Exit; + OpenDialog.Filename := Filename; + // tell application, that selection has changed + OpenDialog.DoSelectionChange; + if (OpenDialog.OnFolderChange <> nil) and + (ExtractFilePath(Filename) <> ExtractFilePath(OldFilename)) then + OpenDialog.DoFolderChange; + // show some information + FileDetailLabel := gtk_object_get_data(PGtkObject(OpenDialog.Handle), 'FileDetailLabel'); + if FileDetailLabel = nil then + Exit; + if FileExists(Filename) then + Details := GetFileDescription(Filename) + else + Details := Format(rsFileInfoFileNotFound, [Filename]); + gtk_label_set_text(PGtkLabel(FileDetailLabel), PChar(Details)); +end; + +// ------------------------ Signals -------------------------------------------- + +{------------------------------------------------------------------------------- + function GTKDialogSelectRowCB + Params: widget: PGtkWidget; data: gPointer + Result: GBoolean + + This function is called, whenever a row is selected in a commondialog +-------------------------------------------------------------------------------} +function gtkDialogSelectRowCB(widget: PGtkWidget; Row, Column: gInt; + bevent: pgdkEventButton; data: gPointer): GBoolean; cdecl; +var + theDialog: TCommonDialog; + MenuWidget: PGtkWidget; + AFilterEntry: PFileSelFilterEntry; + FileSelWidget: PGtkFileSelection; + ShiftState: TShiftState; + loop : gint; + startRow : gint; + endRow : gint; +begin + //debugln('GTKDialogSelectRowCB A '); + Result:=CallBackDefaultReturn; + if (Data=nil) or (BEvent=nil) or (Column=0) or (Row=0) then ; + theDialog:=TCommonDialog(GetLCLObject(Widget)); + if (theDialog is TOpenDialog) then begin + // only process the callback if there is event data. If there isn't any + // event data that means it was called due to a direct function call of the + // widget and not an actual mouse click on the widget. + FileSelWidget:=PGtkFileSelection(theDialog.Handle); + if (bevent <> nil) and (gdk_event_get_type(bevent) = GDK_2BUTTON_PRESS) + and (FileSelWidget^.dir_list = widget) then begin + MenuWidget := gtk_object_get_data(PGtkObject(FileSelWidget), + 'LCLFilterMenu'); + if MenuWidget <> nil then begin + AFilterEntry := gtk_object_get_data(PGtkObject( + gtk_menu_get_active(PGtkMenu(MenuWidget))), 'LCLIsFilterMenuItem'); + if (AFilterEntry<>nil) and (AFilterEntry^.Mask<>nil) then + PopulateFileAndDirectoryLists(FileSelWidget,AFilterEntry^.Mask); + end; + end + else if (bevent <> nil) + and (ofAllowMultiSelect in TOpenDialog(theDialog).Options) + and (FileSelWidget^.file_list=widget) then begin + // multi selection + ShiftState := GTKEventStateToShiftState(BEvent^.State); + if ssShift in ShiftState then begin + if LastFileSelectRow <> -1 then begin + startRow := LastFileSelectRow; + endRow := row; + if LastFileSelectRow > row then begin + startRow := row; + endRow := LastFileSelectRow; + end; + for loop := startRow to endRow do begin + gtk_clist_select_row(PGtkCList(widget), loop, column); + end; + end; + end + else if not (ssCtrl in ShiftState) then begin + gtk_clist_unselect_all(PGtkCList(widget)); + gtk_clist_select_row(PGtkCList(widget), row, column); + end; + LastFileSelectRow := row; + end; + UpdateDetailView(TOpenDialog(theDialog)); + end; +end; + +{------------------------------------------------------------------------------- + function gtkDialogHelpclickedCB + Params: widget: PGtkWidget; data: gPointer + Result: GBoolean + + This function is called, whenever the user clicks the help button in a + commondialog +-------------------------------------------------------------------------------} +function gtkDialogHelpclickedCB(widget: PGtkWidget; data: gPointer): GBoolean; cdecl; +var + theDialog : TCommonDialog; +begin + Result := CallBackDefaultReturn; + if (Widget=nil) then ; + theDialog := TCommonDialog(data); + if theDialog is TOpenDialog then begin + if TOpenDialog(theDialog).OnHelpClicked<>nil then + TOpenDialog(theDialog).OnHelpClicked(theDialog); + end; +end; + +{------------------------------------------------------------------------------- + function gtkDialogApplyclickedCB + Params: widget: PGtkWidget; data: gPointer + Result: GBoolean + + This function is called, whenever the user clicks the Apply button in a + commondialog +-------------------------------------------------------------------------------} +function gtkDialogApplyclickedCB(widget: PGtkWidget; data: gPointer): GBoolean; + cdecl; +var + theDialog : TCommonDialog; + FontName: string; + ALogFont: TLogFont; + {$ifdef GTK2} + FontDesc: PPangoFontDescription; + {$endif} +begin + Result := CallBackDefaultReturn; + if (Widget=nil) then ; + theDialog := TCommonDialog(data); + if (theDialog is TFontDialog) + and (fdApplyButton in TFontDialog(theDialog).Options) + and (Assigned(TFontDialog(theDialog).OnApplyClicked)) then begin + FontName := gtk_font_selection_dialog_get_font_name( + pgtkfontselectiondialog(theDialog.Handle)); + if IsFontNameXLogicalFontDesc(FontName) then begin + // extract basic font attributes from the font name in XLFD format + ALogFont:=XLFDNameToLogFont(FontName); + TFontDialog(theDialog).Font.Assign(ALogFont); + // set the font name in XLFD format + // a font name in XLFD format overrides in the gtk interface all other font + // settings. + TFontDialog(theDialog).Font.Name := FontName; + end else begin + {$ifdef GTK2} + FontDesc := pango_font_description_from_string(PChar(FontName)); + with TFontDialog(theDialog).Font do + begin + BeginUpdate; + Size := pango_font_description_get_size(FontDesc) div PANGO_SCALE; + if pango_font_description_get_weight(FontDesc) >= PANGO_WEIGHT_BOLD then + Style := Style + [fsBold] + else + Style := Style - [fsBold]; + if pango_font_description_get_style(FontDesc) > PANGO_STYLE_NORMAL then + Style := Style + [fsItalic] + else + Style := Style - [fsItalic]; + Name := pango_font_description_get_family(FontDesc); + EndUpdate; + end; + pango_font_description_free(FontDesc); + {$else} + debugln('Gtk1 should have valid XLogicalFontDesc!'); + {$endif} + end; + TFontDialog(theDialog).OnApplyClicked(theDialog); + end; +end; + +function gtkDialogOKclickedCB( widget: PGtkWidget; data: gPointer) : GBoolean; cdecl; +var + theDialog : TCommonDialog; + Fpointer : Pointer; + // colordialog + colorsel : PGtkColorSelection; + newColor : TGdkColor; + // fontdialog + FontName : String; + ALogFont : TLogFont; + // filedialog + rowNum : gint; + fileInfo : PGChar; + {$IfDef GTK2} + fileList : PPgchar; + FontDesc: PPangoFontDescription; + {$else} + cListRow : PGList; + fileList : PGTKCList; + {$EndIf} + DirName : string; + FileName : string; + Files: TStringList; + CurFilename: string; + //SelectedFont: PGdkFont; + + function CheckOpenedFilename(var AFilename: string): boolean; + {$IFDEF GTK1} + var + MenuWidget: PGtkWidget; + AFilterEntry: PFileSelFilterEntry; + {$ENDIF} + begin + Result:=true; + {$IFDEF GTK1} + // check if entered file are a real directory + if DirectoryExists(AFileName) then + begin + // if only interested in directories, then it's done + if TheDialog is TSelectDirectoryDialog then + begin + result := True; + exit; + end; + // if allowed then jump to that directory + if not (ofNoChangeDir in TOpenDialog(TheDialog).Options) then + begin + // change dir + gtk_file_selection_set_filename(PGtkFileSelection(FPointer), + PChar(AppendPathDelim(AFileName))); + + // populate file list + MenuWidget := gtk_object_get_data(PGtkObject(PGtkFileSelection(FPointer)), 'LCLFilterMenu'); + if (MenuWidget <> nil) then begin + AFilterEntry := gtk_object_get_data(PGtkObject(gtk_menu_get_active( + PGtkMenu(MenuWidget))), 'LCLIsFilterMenuItem'); + if ((AFilterEntry<>nil) and (AFilterEntry^.Mask<>nil)) then + PopulateFileAndDirectoryLists(PGtkFileSelection(FPointer), AFilterEntry^.Mask); + end; + end; + // wait for correct input + result:=False; + Exit; + end; + + // maybe user entered nonexistent dir + if ((AFileName<>'') and (IsPathDelimiter(AFileName, Length(AFileName)))) then + begin + // cant jump to nonexistent dir + if not (ofNoChangeDir in TOpenDialog(TheDialog).Options) then + MessageDlg(rsfdDirectoryMustExist, Format(rsfdDirectoryNotExist,[AFileName]), + mtError, [mbCancel], 0); // GTK2 shows "The folder contents could not be displayed" + // wait for correct input + result:=False; + Exit; + end; + + // check if user selected a file while requesting a directory + if (AFileName<>'') and (TheDialog is TSelectDirectoryDialog) then begin + if DirectoryExists(ExtractFilePath(AFileName)) then begin + AFileName:=ExtractFilePath(AFileName); + result:=true; + exit; + end; + end; + + {$ENDIF} + // maybe file already exists + if (ofOverwritePrompt in TOpenDialog(theDialog).Options) + and FileExists(AFilename) then + begin + Result := MessageDlg(rsfdOverwriteFile, + Format(rsfdFileAlreadyExists,[AFileName]), + mtConfirmation,[mbOk,mbCancel],0)=mrOk; + if not Result then exit; + end; + end; + + procedure AddFile(List: TStrings; const NewFile: string); + var + i: Integer; + begin + for i:=0 to List.Count-1 do + if List[i]=NewFile then exit; + List.Add(NewFile); + end; + +begin + Result := True; + if (Widget=nil) then ; + theDialog := TCommonDialog(data); + FPointer := Pointer(theDialog.Handle); + + if theDialog is TFileDialog then + begin + {$IfDef GTK2} + FileName:=gtk_file_chooser_get_filename(PGtkFileChooser(FPointer)); + {$ELSE} + FileName:=gtk_file_selection_get_filename( + PGtkFileSelection(FPointer)); + {$ENDIF} + if theDialog is TOpenDialog then + begin + // check extra options + if ofAllowMultiSelect in TOpenDialog(theDialog).Options then + begin + DirName:=ExtractFilePath(FileName); + TFileDialog(data).FileName := ''; + Files:=TStringList(TFileDialog(theDialog).Files); + Files.Clear; + if (Filename<>'') then begin + Result:=CheckOpenedFilename(Filename); + if not Result then exit; + AddFile(Files,FileName); + end; + {$IfDef GTK2} + fileList := gtk_file_selection_get_selections(PGtkFileSelection(FPointer)); + rowNum := 0; + While FileList^ <> nil do + begin + fileInfo := FileList^; + CurFilename:=fileInfo; // convert PChar to AnsiString (not typecast) + if (CurFilename<>'') and (Files.IndexOf(CurFilename)<0) then begin + CurFilename:=DirName+fileInfo; + Result:=CheckOpenedFilename(CurFilename); + if not Result then exit; + Files.Add(CurFilename); + end; + inc(FileList); + inc(rowNum); + end; + Dec(FileList, rowNum); + g_strfreev(fileList); + {$Else} + fileList := PGtkCList(PGtkFileSelection(FPointer)^.file_list); + rowNum := 0; + cListRow := fileList^.row_list; + while cListRow <> nil do + begin + if PGtkCListRow(cListRow^.data)^.state = GTK_STATE_SELECTED then + begin + if gtk_clist_get_cell_type(fileList, rowNum, 0) = GTK_CELL_TEXT + then begin + gtk_clist_get_text(fileList, rowNum, 0, @fileInfo); + CurFilename:=DirName+fileInfo; + Result:=CheckOpenedFilename(CurFilename); + if not Result then exit; + AddFile(Files,CurFilename); + end; + end; + // get next row from list + rowNum := rowNum + 1; + cListRow := g_list_next(cListRow); + end; + {$EndIf} + end else begin + Result:=CheckOpenedFilename(Filename); + if not Result then exit; + TFileDialog(data).FileName := Filename; + end; + end + else + begin + TFileDialog(data).FileName := Filename; + end; + end + else if theDialog is TColorDialog then + begin + colorSel := PGtkColorSelection(PGtkColorSelectionDialog(FPointer)^.colorsel); + gtk_color_selection_get_current_color(colorsel, @newColor); + TColorDialog(theDialog).Color := TGDKColorToTColor(newcolor); + {$IFDEF VerboseColorDialog} + DebugLn('gtkDialogOKclickedCB ',DbgS(TColorDialog(theDialog).Color)); + {$ENDIF} + end + else if theDialog is TFontDialog then + begin + Assert(False, 'Trace:Pressed OK in FontDialog'); + FontName := gtk_font_selection_dialog_get_font_name( + pgtkfontselectiondialog(FPointer)); + //debugln('gtkDialogOKclickedCB FontName=',FontName); + //SelectedFont:=gdk_font_load(PChar(FontName)); + //debugln('gtkDialogOKclickedCB ',dbgs(SelectedFont)); + + if IsFontNameXLogicalFontDesc(FontName) then begin + // extract basic font attributes from the font name in XLFD format + ALogFont:=XLFDNameToLogFont(FontName); + TFontDialog(theDialog).Font.Assign(ALogFont); + // set the font name in XLFD format + // a font name in XLFD format overrides in the gtk interface all other font + // settings. + TFontDialog(theDialog).Font.Name := FontName; + end else begin + {$ifdef GTK2} + FontDesc := pango_font_description_from_string(PChar(FontName)); + with TFontDialog(theDialog).Font do + begin + BeginUpdate; + Size := pango_font_description_get_size(FontDesc) div PANGO_SCALE; + if pango_font_description_get_weight(FontDesc) >= PANGO_WEIGHT_BOLD then + Style := Style + [fsBold] + else + Style := Style - [fsBold]; + if pango_font_description_get_style(FontDesc) > PANGO_STYLE_NORMAL then + Style := Style + [fsItalic] + else + Style := Style - [fsItalic]; + Name := pango_font_description_get_family(FontDesc); + EndUpdate; + end; + pango_font_description_free(FontDesc); + {$else} + debugln('Gtk1 should have valid XLogicalFontDesc!'); + {$endif} + end; + + Assert(False, 'Trace:-----'+TFontDialog(theDialog).Font.Name+'----'); + end; + + StoreCommonDialogSetup(theDialog); + theDialog.UserChoice := mrOK; +end; + +{------------------------------------------------------------------------------- + function gtkDialogCancelclickedCB + Params: widget: PGtkWidget; data: gPointer + Result: GBoolean + + This function is called, whenever the user clicks the cancel button in a + commondialog +-------------------------------------------------------------------------------} +function gtkDialogCancelclickedCB(widget: PGtkWidget; data: gPointer): GBoolean; + cdecl; +var + theDialog : TCommonDialog; +begin + Result := CallBackDefaultReturn; + if (Widget=nil) then ; + theDialog := TCommonDialog(data); + if theDialog is TFileDialog then + begin + TFileDialog(data).FileName := ''; + end; + StoreCommonDialogSetup(theDialog); + theDialog.UserChoice := mrCancel; +end; + +{------------------------------------------------------------------------------- + function GTKDialogRealizeCB + Params: Widget: PGtkWidget; Data: Pointer + Result: GBoolean + + This function is called, whenever a commondialog window is realized +-------------------------------------------------------------------------------} +function GTKDialogRealizeCB(Widget: PGtkWidget; Data: Pointer): GBoolean; cdecl; +var + LCLComponent: TObject; +begin + if (Data=nil) then ; + gdk_window_set_events(GetControlWindow(Widget), + gdk_window_get_events(GetControlWindow(Widget)) + or GDK_KEY_RELEASE_MASK or GDK_KEY_PRESS_MASK); + LCLComponent:=GetLCLObject(Widget); + if LCLComponent is TCommonDialog then + TCommonDialog(LCLComponent).DoShow; + Result:=true; +end; + +{------------------------------------------------------------------------------- + function gtkDialogCloseQueryCB + Params: widget: PGtkWidget; data: gPointer + Result: GBoolean + + This function is called, before a commondialog is destroyed +-------------------------------------------------------------------------------} +function gtkDialogCloseQueryCB(widget: PGtkWidget; data: gPointer): GBoolean; + cdecl; +var + theDialog : TCommonDialog; + CanClose: boolean; +begin + Result := False; // true = do nothing, false = destroy or hide window + if (Data=nil) then ; + // data is not the commondialog. Get it manually. + theDialog := TCommonDialog(GetLCLObject(Widget)); + if theDialog=nil then exit; + if theDialog.OnCanClose<>nil then begin + CanClose:=True; + theDialog.OnCanClose(theDialog,CanClose); + Result:=not CanClose; + end; + if not Result then begin + StoreCommonDialogSetup(theDialog); + DestroyCommonDialogAddOns(theDialog); + end; +end; + +{------------------------------------------------------------------------------- + function gtkDialogDestroyCB + Params: widget: PGtkWidget; data: gPointer + Result: GBoolean + + This function is called, when a commondialog is destroyed +-------------------------------------------------------------------------------} +function gtkDialogDestroyCB(widget: PGtkWidget; data: gPointer): GBoolean; cdecl; +begin + Result := True; + if (Widget=nil) then ; + TCommonDialog(data).UserChoice := mrAbort; + TCommonDialog(data).Close; +end; + +{------------------------------------------------------------------------------- + function GTKDialogKeyUpDownCB + Params: Widget: PGtkWidget; Event : pgdkeventkey; Data: gPointer + Result: GBoolean + + This function is called, whenever a key is pressed or released in a common + dialog window +-------------------------------------------------------------------------------} +function GTKDialogKeyUpDownCB(Widget: PGtkWidget; Event : pgdkeventkey; + Data: gPointer) : GBoolean; cdecl; +begin + //debugln('GTKDialogKeyUpDownCB A '); + Result:=CallBackDefaultReturn; + + if (Widget=nil) then ; + case gdk_event_get_type(Event) of + + GDK_KEY_RELEASE, GDK_KEY_PRESS: + begin + if Event^.KeyVal = GDK_KEY_Escape + then begin + StoreCommonDialogSetup(TCommonDialog(data)); + TCommonDialog(data).UserChoice:=mrCancel; + end; + if (TCommonDialog(data) is TOpenDialog) then begin + UpdateDetailView(TOpenDialog(data)); + end; + end; + + end; +end; + +{------------------------------------------------------------------------------- + function GTKDialogFocusInCB + Params: widget: PGtkWidget; data: gPointer + Result: GBoolean + + This function is called, when a widget of a commondialog gets focus +-------------------------------------------------------------------------------} +function GTKDialogFocusInCB(widget: PGtkWidget; data: gPointer): GBoolean; + cdecl; +var + theDialog: TCommonDialog; +begin + //debugln('GTKDialogFocusInCB A '); + Result:=CallBackDefaultReturn; + if (Data=nil) then ; + theDialog:=TCommonDialog(GetLCLObject(Widget)); + if (theDialog is TOpenDialog) then begin + UpdateDetailView(TOpenDialog(theDialog)); + end; +end; + +{------------------------------------------------------------------------------- + function GTKDialogMenuActivateCB + Params: widget: PGtkWidget; data: gPointer + Result: GBoolean + + This function is called, whenever a menu of a commondialog is activated +-------------------------------------------------------------------------------} +function GTKDialogMenuActivateCB(widget: PGtkWidget; data: gPointer): GBoolean; + cdecl; +var + theDialog: TCommonDialog; + + procedure CheckFilterActivated(FilterWidget: PGtkWidget); + var + AFilterEntry: PFileSelFilterEntry; + begin + if FilterWidget=nil then exit; + AFilterEntry:=gtk_object_get_data(PGtkObject(FilterWidget), + 'LCLIsFilterMenuItem'); + if (AFilterEntry<>nil) and (AFilterEntry^.Mask<>nil) then + begin + PopulateFileAndDirectoryLists(PGtkFileSelection(theDialog.Handle), + AFilterEntry^.Mask); + TFileDialog(TheDialog).IntfFileTypeChanged(AFilterEntry^.FilterIndex + 1); + UpdateDetailView(TOpenDialog(theDialog)); + end; + end; + +var + AHistoryEntry: PFileSelHistoryEntry; + {$IFDEF Gtk1} + FilterMenu, ActiveFilterMenuItem: PGtkWidget; + {$ENDIF} +begin + Result:=false; + if (Data=nil) then ; + theDialog:=TCommonDialog(GetNearestLCLObject(Widget)); + if (theDialog is TOpenDialog) then begin + // check if history activated + AHistoryEntry:=gtk_object_get_data(PGtkObject(Widget), + 'LCLIsHistoryMenuItem'); + if (AHistoryEntry<>nil) and (AHistoryEntry^.Filename<>nil) then begin + // user has choosen a history file + // -> select it in the filedialog + {$IFDEF GTK1} + gtk_file_selection_complete(PGtkFileSelection(theDialog.Handle), + AHistoryEntry^.Filename); + // restore filter + if DirPathExists(AHistoryEntry^.Filename) then begin + FilterMenu:=gtk_object_get_data(PGtkObject(theDialog.Handle), + 'LCLFilterMenu'); + if FilterMenu<>nil then begin + ActiveFilterMenuItem:=gtk_menu_get_active(GTK_MENU(FilterMenu)); + CheckFilterActivated(ActiveFilterMenuItem); + end; + end; + {$ELSE} + gtk_file_chooser_set_current_folder(PGtkFileChooser(theDialog.Handle),AHistoryEntry^.Filename); + {$ENDIF} + UpdateDetailView(TOpenDialog(theDialog)); + end; + {$IFDEF GTK1} + // check if filter activated + CheckFilterActivated(Widget); + {$ENDIF} + end; +end; + +// -------------------- END OF Signals ----------------------------------------- + {------------------------------------------------------------------------------ Method: SetColorDialogColor Params: ColorSelection : a gtk color selection dialog; @@ -166,10 +832,41 @@ begin GtkWindowShowModal(GtkWindow); end; -class function TGtkWSCommonDialog.CreateHandle(const ACommonDialog: TCommonDialog): THandle; +class procedure TGtkWSCommonDialog.SetCallbacks(const AGtkWidget: PGtkWidget; + const AWidgetInfo: PWidgetInfo); begin - { TODO: cleanup } - Result := TGtkWidgetSet(WidgetSet).CreateComponent(ACommonDialog); + g_signal_connect(PGtkObject(AGtkWidget), + 'destroy', gtk_Signal_Func(@gtkDialogDestroyCB), AWidgetInfo^.LCLObject); + g_signal_connect(PGtkObject(AGtkWidget), + 'delete-event', gtk_Signal_Func(@gtkDialogCloseQueryCB), AWidgetInfo^.LCLObject); + g_signal_connect(PGtkObject(AGtkWidget), + 'key-press-event', gtk_Signal_Func(@GTKDialogKeyUpDownCB), AWidgetInfo^.LCLObject); + g_signal_connect(PGtkObject(AGtkWidget), + 'key-release-event', gtk_Signal_Func(@GTKDialogKeyUpDownCB), AWidgetInfo^.LCLObject); + g_signal_connect(PGtkObject(AGtkWidget), + 'realize', gtk_Signal_Func(@GTKDialogRealizeCB), AWidgetInfo^.LCLObject); +end; + +class procedure TGtkWSCommonDialog.SetSizes(const AGtkWidget: PGtkWidget; + const AWidgetInfo: PWidgetInfo); +var + NewWidth, NewHeight: integer; +begin + // set default size + NewWidth := TCommonDialog(AWidgetInfo^.LCLObject).Width; + if NewWidth <= 0 then + NewWidth := -2; // -2 = let the window manager decide + NewHeight := TCommonDialog(AWidgetInfo^.LCLObject).Height; + if NewHeight<=0 then + NewHeight := -2; // -2 = let the window manager decide + if (NewWidth > 0) or (NewHeight > 0) then + gtk_window_set_default_size(PGtkWindow(AGtkWidget), NewWidth, NewHeight); +end; + +class function TGtkWSCommonDialog.CreateHandle(const ACommonDialog: TCommonDialog): THandle; +begin + Result := 0; + DebugLn('TGtkWSCommonDialog.CreateHandle is generic dialog handle constructor => implement CreateHandle for: ', dbgsName(ACommonDialog)) end; class procedure TGtkWSCommonDialog.DestroyHandle(const ACommonDialog: TCommonDialog); @@ -178,6 +875,469 @@ begin TGtkWidgetSet(WidgetSet).DestroyLCLComponent(ACommonDialog); end; +{ TGtkWSColorDialog } + +class procedure TGtkWSColorDialog.SetCallbacks(const AGtkWidget: PGtkWidget; + const AWidgetInfo: PWidgetInfo); +begin + TGtkWSCommonDialog.SetCallbacks(AGtkWidget, AWidgetInfo); + g_signal_connect(PGtkObject(PGtkColorSelectionDialog(AGtkWidget)^.ok_button), + 'clicked', gtk_signal_func(@gtkDialogOKclickedCB), AWidgetInfo^.LCLObject); + g_signal_connect(PGtkObject(PGtkColorSelectionDialog(AGtkWidget)^.cancel_button), + 'clicked', gtk_signal_func(@gtkDialogCancelclickedCB), AWidgetInfo^.LCLObject); +end; + +class function TGtkWSColorDialog.CreateHandle(const ACommonDialog: TCommonDialog): THandle; +var + Widget: PGtkWidget; + WidgetInfo: PWidgetInfo; +begin + Widget := gtk_color_selection_dialog_new(PChar(ACommonDialog.Title)); + Result := THandle(PtrUInt(Widget)); + WidgetInfo := CreateWidgetInfo(Widget); + WidgetInfo^.LCLObject := ACommonDialog; + TGtkWSCommonDialog.SetSizes(Widget, WidgetInfo); + SetCallbacks(Widget, WidgetInfo); +end; + +{ TGtkWSFileDialog } + +class procedure TGtkWSFileDialog.SetCallbacks(const AGtkWidget: PGtkWidget; + const AWidgetInfo: PWidgetInfo); +begin + TGtkWSCommonDialog.SetCallbacks(AGtkWidget, AWidgetInfo); + {****This is a major hack put by Cliff Baeseman to solve + a gtk win32 dll implementation problem where the headers implementation + does not match the linux version**** } + {$IFNDEF WIN32} + g_signal_connect(gtk_object(PGtkFileSelection(AGtkWidget)^.ok_button), + 'clicked', gtk_signal_func(@gtkDialogOKclickedCB), AWidgetInfo^.LCLObject); + g_signal_connect(gtk_object(PGtkFileSelection(AGtkWidget)^.cancel_button), + 'clicked', gtk_signal_func(@gtkDialogCancelclickedCB), AWidgetInfo^.LCLObject); + {$ELSE} + g_signal_connect(gtk_object(PGtkFileSelection(AGtkWidget)^.cancel_button), + 'clicked', gtk_signal_func(@gtkDialogOKclickedCB), AWidgetInfo^.LCLObject); + g_signal_connect(gtk_object(PGtkFileSelection(AGtkWidget)^.help_button), + 'clicked', gtk_signal_func(@gtkDialogCancelclickedCB), AWidgetInfo^.LCLObject); + {$ENDIF} +end; + +class function TGtkWSFileDialog.CreateHandle(const ACommonDialog: TCommonDialog): THandle; +var + Widget: PGtkWidget; + WidgetInfo: PWidgetInfo; +begin + // for: csFileDialog, csOpenFileDialog, csSaveFileDialog, csSelectDirectoryDialog, csPreviewFileDialog + Widget := gtk_file_selection_new(PChar(ACommonDialog.Title)); + + Result := THandle(PtrUInt(Widget)); + WidgetInfo := CreateWidgetInfo(Widget); + WidgetInfo^.LCLObject := ACommonDialog; + TGtkWSCommonDialog.SetSizes(Widget, WidgetInfo); + SetCallbacks(Widget, WidgetInfo); +end; + +{ TGtkWSOpenDialog } + +{------------------------------------------------------------------------------ + Function: TGtkWidgetSet.CreateOpenDialogFilter + Params: OpenDialog: TOpenDialog; SelWidget: PGtkWidget + Returns: - + + Adds a Filter pulldown to a gtk file selection dialog. Returns the + inital filter mask. + ------------------------------------------------------------------------------} +class function TGtkWSOpenDialog.CreateOpenDialogFilter(OpenDialog: TOpenDialog; SelWidget: PGtkWidget): string; +var + FilterList: TFPList; + HBox, LabelWidget, FilterPullDownWidget, + MenuWidget, MenuItemWidget: PGtkWidget; + i, j, CurMask: integer; + s: String; +begin + ExtractFilterList(OpenDialog.Filter,FilterList,false); + if FilterList.Count>0 then begin + + // create a HBox so that the filter pulldown is left justified + HBox:=gtk_hbox_new(false,0); + gtk_object_set_data(PGtkObject(SelWidget), 'LCLFilterHBox', HBox); + gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(SelWidget)^.main_vbox), + HBox,false,false,0); + + // create the label 'Filter:' + s:=rsgtkFilter; + LabelWidget:=gtk_label_new(PChar(s)); + gtk_box_pack_start(GTK_BOX(HBox),LabelWidget,false,false,5); + gtk_widget_show(LabelWidget); + + // create the pull down + FilterPullDownWidget:=gtk_option_menu_new; + gtk_object_set_data(PGtkObject(SelWidget), 'LCLFilterPullDown', + FilterPullDownWidget); + gtk_box_pack_start(GTK_BOX(HBox),FilterPullDownWidget,false,false,5); + gtk_widget_show(FilterPullDownWidget); + gtk_widget_show(HBox); + + // create the menu (the content of the pull down) + MenuWidget:=gtk_menu_new; + SetLCLObject(MenuWidget,OpenDialog); + for i:=0 to FilterList.Count-1 do begin + // create the menu items in the filter menu + MenuItemWidget:=gtk_menu_item_new_with_label( + PFileSelFilterEntry(FilterList[i])^.Description); + // connect the new MenuItem to the FilterList entry + gtk_object_set_data(PGtkObject(MenuItemWidget), 'LCLIsFilterMenuItem', + FilterList[i]); + // add activation signal and add to menu + g_signal_connect(GTK_OBJECT(MenuItemWidget), 'activate', + gtk_signal_func(@GTKDialogMenuActivateCB), + OpenDialog); + gtk_menu_append(MenuWidget, MenuItemWidget); + gtk_widget_show(MenuItemWidget); + end; + gtk_widget_show(MenuWidget); + gtk_option_menu_set_menu(GTK_OPTION_MENU(FilterPullDownWidget), + MenuWidget); + end else begin + MenuWidget:=nil; + end; + gtk_object_set_data(PGtkObject(SelWidget), 'LCLFilterMenu', MenuWidget); + gtk_object_set_data(PGtkObject(SelWidget), 'LCLFilterList', FilterList); + + // set the initial filter + Result := 'none'; { Don't use '' as null return as this is used for *.* } + if FilterList.Count>0 then begin + i:=0; + j:=OpenDialog.FilterIndex - 1; // FilterIndex is 1 based + if j<0 then j:=0; + CurMask:=0; + while (i0 then begin + + // create the HistoryList where the current state of the history is stored + HistoryList:=TFPList.Create; + for i:=0 to OpenDialog.HistoryList.Count-1 do begin + s:=OpenDialog.HistoryList[i]; + if s<>'' then begin + New(AHistoryEntry); + HistoryList.Add(AHistoryEntry); + AHistoryEntry^.Filename := StrAlloc(length(s)+1); + StrPCopy(AHistoryEntry^.Filename, s); + AHistoryEntry^.MenuItem:=nil; + end; + end; + + // create a HBox so that the history is left justified + HBox:=gtk_hbox_new(false,0); + gtk_object_set_data(PGtkObject(SelWidget), 'LCLHistoryHBox', HBox); + {$IFDEF GTK1} + gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(SelWidget)^.main_vbox), + HBox,false,false,0); + {$ELSE} + gtk_file_chooser_set_extra_widget(PGtkDialog(SelWidget),HBox); + {$ENDIF} + + // create the label 'History:' + s:=rsgtkHistory; + LabelWidget:=gtk_label_new(PChar(s)); + gtk_box_pack_start(GTK_BOX(HBox),LabelWidget,false,false,5); + gtk_widget_show(LabelWidget); + + // create the pull down + HistoryPullDownWidget:=gtk_option_menu_new; + gtk_object_set_data(PGtkObject(SelWidget), 'LCLHistoryPullDown', + HistoryPullDownWidget); + gtk_box_pack_start(GTK_BOX(HBox),HistoryPullDownWidget,false,false,5); + gtk_widget_show(HistoryPullDownWidget); + gtk_widget_show_all(HBox); + + // create the menu (the content of the pull down) + MenuWidget:=gtk_menu_new; + SetLCLObject(MenuWidget,OpenDialog); + for i:=0 to HistoryList.Count-1 do begin + // create the menu items in the history menu + MenuItemWidget:=gtk_menu_item_new_with_label( + PFileSelHistoryEntry(HistoryList[i])^.Filename); + // connect the new MenuItem to the HistoryList entry + gtk_object_set_data(PGtkObject(MenuItemWidget), 'LCLIsHistoryMenuItem', + HistoryList[i]); + // add activation signal and add to menu + g_signal_connect(GTK_OBJECT(MenuItemWidget), 'activate', + gtk_signal_func(@GTKDialogMenuActivateCB), + OpenDialog); + gtk_menu_append(MenuWidget, MenuItemWidget); + gtk_widget_show(MenuItemWidget); + end; + gtk_widget_show(MenuWidget); + gtk_option_menu_set_menu(GTK_OPTION_MENU(HistoryPullDownWidget), + MenuWidget); + end else begin + MenuWidget:=nil; + HistoryList:=nil + end; + gtk_object_set_data(PGtkObject(SelWidget), 'LCLHistoryMenu', MenuWidget); + gtk_object_set_data(PGtkObject(SelWidget), 'LCLHistoryList', HistoryList); +end; + +class function TGtkWSOpenDialog.CreateHandle(const ACommonDialog: TCommonDialog): THandle; +var + SelWidget: PGtkWidget; + OpenDialog: TOpenDialog absolute ACommonDialog; + + FileDetailLabel, HBox, FrameWidget: PGtkWidget; + FileSelWidget: PGtkFileSelection; + InitialFilter: string; +begin + Result := TGtkWSFileDialog.CreateHandle(ACommonDialog); + SelWidget := PGtkWidget(Result); + + //DebugLn(['TGtkWidgetSet.InitializeOpenDialog ']); + FileSelWidget := GTK_FILE_SELECTION(SelWidget); + + // Help button + if (ofShowHelp in OpenDialog.Options) + and (FileSelWidget^.Help_Button<>nil) then begin + gtk_widget_show(FileSelWidget^.Help_Button); + g_signal_connect( gtk_object(FileSelWidget^.help_button), + 'clicked', gtk_signal_func(@gtkDialogHelpclickedCB), OpenDialog); + end; + + // connect selection entry (edit field for filename) + if (FileSelWidget^.selection_entry<>nil) then begin + SetLCLObject(FileSelWidget^.selection_entry,OpenDialog); + g_signal_connect( + gtk_object(FileSelWidget^.selection_entry), + 'key-press-event', gtk_signal_func(@GTKDialogKeyUpDownCB), + OpenDialog); + g_signal_connect( + gtk_object(FileSelWidget^.selection_entry), + 'focus-in-event', gtk_signal_func(@GTKDialogFocusInCB), OpenDialog); + end; + + // connect dir list (list of directories) + if (FileSelWidget^.dir_list<>nil) then begin + SetLCLObject(FileSelWidget^.dir_list,OpenDialog); + g_signal_connect(gtk_object(FileSelWidget^.dir_list), + 'select-row', gtk_signal_func(@GTKDialogSelectRowCB), OpenDialog); + end; + + // connect file list (list of files in current directory) + if (FileSelWidget^.file_list<>nil) then begin + LastFileSelectRow := -1; + SetLCLObject(FileSelWidget^.file_list,OpenDialog); + g_signal_connect(gtk_object(FileSelWidget^.file_list), + 'select-row', gtk_signal_func(@GTKDialogSelectRowCB), OpenDialog); + if ofAllowMultiSelect in OpenDialog.Options then + gtk_clist_set_selection_mode( + PGtkCList(FileSelWidget^.file_list),GTK_SELECTION_MULTIPLE); + end; + + // History List - a frame with an option menu + CreateOpenDialogHistory(OpenDialog, SelWidget); + + // Filter - a frame with an option menu + InitialFilter := CreateOpenDialogFilter(OpenDialog,SelWidget); + + // Details - a frame with a label + if (ofViewDetail in OpenDialog.Options) then begin + // create the frame around the information + FrameWidget:=gtk_frame_new(PChar(rsFileInformation)); + gtk_box_pack_start(GTK_BOX(FileSelWidget^.main_vbox), + FrameWidget,false,false,0); + gtk_widget_show(FrameWidget); + // create a HBox, so that the information is left justified + HBox:=gtk_hbox_new(false,0); + gtk_container_add(GTK_CONTAINER(FrameWidget), HBox); + // create the label for the file information + FileDetailLabel:=gtk_label_new(PChar(rsDefaultFileInfoValue)); + gtk_box_pack_start(GTK_BOX(HBox),FileDetailLabel,false,false,5); + gtk_widget_show_all(HBox); + end else + FileDetailLabel:=nil; + gtk_object_set_data(PGtkObject(SelWidget), 'FileDetailLabel', + FileDetailLabel); + + // preview + if (OpenDialog is TPreviewFileDialog) then + CreatePreviewDialogControl(TPreviewFileDialog(OpenDialog),SelWidget); + + // set initial filename + if OpenDialog.Filename<>'' then + gtk_file_selection_set_filename(FileSelWidget,PChar(OpenDialog.Filename)); + + if InitialFilter <> 'none' then + PopulateFileAndDirectoryLists(FileSelWidget, InitialFilter); +end; + +{ TGtkWSFontDialog } + +class procedure TGtkWSFontDialog.SetCallbacks(const AGtkWidget: PGtkWidget; + const AWidgetInfo: PWidgetInfo); +begin + TGtkWSCommonDialog.SetCallbacks(AGtkWidget, AWidgetInfo); + // connect Ok, Cancel and Apply Button + g_signal_connect( + PGtkObject(PGtkFontSelectionDialog(AGtkWidget)^.ok_button), + 'clicked', gtk_signal_func(@gtkDialogOKclickedCB), AWidgetInfo^.LCLObject); + g_signal_connect( + PGtkObject(PGtkFontSelectionDialog(AGtkWidget)^.cancel_button), + 'clicked', gtk_signal_func(@gtkDialogCancelclickedCB), AWidgetInfo^.LCLObject); + g_signal_connect( + PGtkObject(PGtkFontSelectionDialog(AGtkWidget)^.apply_button), + 'clicked', gtk_signal_func(@gtkDialogApplyclickedCB), AWidgetInfo^.LCLObject); +end; + +class function TGtkWSFontDialog.CreateHandle(const ACommonDialog: TCommonDialog): THandle; +{$IFDEF GTK1} +const + FixedFilter: array [0..2] of PChar = ( 'c', 'm', nil ); +{$ENDIF} + +var +{$IFDEF GTK1} + SpacingFilter: PPgchar; + FontType: TGtkFontType; +{$ELSE} + FontDesc: PPangoFontDescription; + TmpStr: pChar; +{$ENDIF} + Widget: PGtkWidget; + WidgetInfo: PWidgetInfo; + FontDialog: TFontDialog absolute ACommonDialog; +begin + Widget := gtk_font_selection_dialog_new(PChar(ACommonDialog.Title)); + + if fdApplyButton in FontDialog.Options then + gtk_widget_show(PGtkFontSelectionDialog(Widget)^.apply_button); + // set preview text + if FontDialog.PreviewText <> '' then + gtk_font_selection_dialog_set_preview_text(PGtkFontSelectionDialog(Widget), + PChar(FontDialog.PreviewText)); + + // set font name in XLFD format + if IsFontNameXLogicalFontDesc(FontDialog.Font.Name) then + gtk_font_selection_dialog_set_font_name(PGtkFontSelectionDialog(Widget), + PChar(FontDialog.Font.Name)) + else + begin + {$IFDEF GTK1} + DebugLn('Gtk1 should have IsFontNameXLogicalFontDesc true!'); + {$ELSE} + FontDesc := pango_font_description_new; + with FontDialog.Font do + begin + pango_font_description_set_size(FontDesc, Size * PANGO_SCALE); + + if fsBold in Style then + pango_font_description_set_weight(FontDesc, PANGO_WEIGHT_BOLD) + else + pango_font_description_set_weight(FontDesc, PANGO_WEIGHT_NORMAL); + + if fsItalic in Style then + pango_font_description_set_style(FontDesc, PANGO_STYLE_ITALIC) + else + pango_font_description_set_style(FontDesc, PANGO_STYLE_NORMAL); + + pango_font_description_set_family(FontDesc, PChar(Name)); + end; + TmpStr := pango_font_description_to_string(FontDesc); + gtk_font_selection_dialog_set_font_name(PGtkFontSelectionDialog(Widget), TmpStr); + g_free(TmpStr); + pango_font_description_free(FontDesc); + {$ENDIF} + end; + + {$IFDEF GTK1} + { This functionality does not seem to be available in GTK2 } + // Honor selected TFontDialogOption flags + SpacingFilter := nil; + if fdFixedPitchOnly in FontDialog.Options then + SpacingFilter := @FixedFilter[0]; + FontType := GTK_FONT_ALL; + if fdScalableOnly in FontDialog.Options then + FontType := GTK_FONT_SCALABLE; + gtk_font_selection_dialog_set_filter(PGtkFontSelectionDialog(Widget), + GTK_FONT_FILTER_BASE, FontType, + nil, nil, nil, nil, SpacingFilter, nil); + {$ENDIF} + + Result := THandle(PtrUInt(Widget)); + WidgetInfo := CreateWidgetInfo(Widget); + WidgetInfo^.LCLObject := ACommonDialog; + TGtkWSCommonDialog.SetSizes(Widget, WidgetInfo); + SetCallbacks(Widget, WidgetInfo); +end; + initialization //////////////////////////////////////////////////// @@ -188,11 +1348,11 @@ initialization //////////////////////////////////////////////////// RegisterWSComponent(TCommonDialog, TGtkWSCommonDialog); // RegisterWSComponent(TFileDialog, TGtkWSFileDialog); -// RegisterWSComponent(TOpenDialog, TGtkWSOpenDialog); + RegisterWSComponent(TOpenDialog, TGtkWSOpenDialog); // RegisterWSComponent(TSaveDialog, TGtkWSSaveDialog); // RegisterWSComponent(TSelectDirectoryDialog, TGtkWSSelectDirectoryDialog); -// RegisterWSComponent(TColorDialog, TGtkWSColorDialog); + RegisterWSComponent(TColorDialog, TGtkWSColorDialog); // RegisterWSComponent(TColorButton, TGtkWSColorButton); -// RegisterWSComponent(TFontDialog, TGtkWSFontDialog); + RegisterWSComponent(TFontDialog, TGtkWSFontDialog); //////////////////////////////////////////////////// end. diff --git a/lcl/interfaces/gtk/gtkwsextdlgs.pp b/lcl/interfaces/gtk/gtkwsextdlgs.pp index 760358e46c..bf9c2c22de 100644 --- a/lcl/interfaces/gtk/gtkwsextdlgs.pp +++ b/lcl/interfaces/gtk/gtkwsextdlgs.pp @@ -36,7 +36,9 @@ type TGtkWSPreviewFileControl = class(TWSPreviewFileControl) private protected + class procedure SetCallbacks(const AGtkWidget: PGtkWidget; const AWidgetInfo: PWidgetInfo); virtual; public + class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override; end; { TGtkWSPreviewFileDialog } @@ -98,6 +100,36 @@ type implementation +{ TGtkWSPreviewFileControl } + +class procedure TGtkWSPreviewFileControl.SetCallbacks( + const AGtkWidget: PGtkWidget; const AWidgetInfo: PWidgetInfo); +begin + TGtkWSWinControl.SetCallbacks(PGtkObject(AGtkWidget), TComponent(AWidgetInfo^.LCLObject)); +end; + +class function TGtkWSPreviewFileControl.CreateHandle( + const AWinControl: TWinControl; const AParams: TCreateParams + ): TLCLIntfHandle; +var + Widget: PGtkWidget; + WidgetInfo: PWidgetInfo; +begin + Widget := GtkWidgetset.CreateSimpleClientAreaWidget(AWinControl, True); + {$IFDEF DebugLCLComponents} + DebugGtkWidgets.MarkCreated(Widget, dbgsName(AWinControl)); + {$ENDIF} + Result := TLCLIntfHandle(PtrUInt(Widget)); + + WidgetInfo := GetWidgetInfo(Widget); + WidgetInfo^.LCLObject := AWinControl; + WidgetInfo^.Style := AParams.Style; + WidgetInfo^.ExStyle := AParams.ExStyle; + WidgetInfo^.WndProc := PtrUInt(AParams.WindowClass.lpfnWndProc); + + SetCallBacks(Widget, WidgetInfo); +end; + initialization //////////////////////////////////////////////////// @@ -106,7 +138,7 @@ initialization // To improve speed, register only classes // which actually implement something //////////////////////////////////////////////////// -// RegisterWSComponent(TPreviewFileControl, TGtkWSPreviewFileControl); + RegisterWSComponent(TPreviewFileControl, TGtkWSPreviewFileControl); // RegisterWSComponent(TPreviewFileDialog, TGtkWSPreviewFileDialog); // RegisterWSComponent(TOpenPictureDialog, TGtkWSOpenPictureDialog); // RegisterWSComponent(TSavePictureDialog, TGtkWSSavePictureDialog); @@ -115,4 +147,4 @@ initialization // RegisterWSComponent(TCalendarDialogForm, TGtkWSCalendarDialogForm); // RegisterWSComponent(TCalendarDialog, TGtkWSCalendarDialog); //////////////////////////////////////////////////// -end. \ No newline at end of file +end. diff --git a/lcl/interfaces/gtk/gtkwsstdctrls.pp b/lcl/interfaces/gtk/gtkwsstdctrls.pp index 9e245dc71c..c1b635c164 100644 --- a/lcl/interfaces/gtk/gtkwsstdctrls.pp +++ b/lcl/interfaces/gtk/gtkwsstdctrls.pp @@ -80,6 +80,8 @@ type protected public {$IFDEF GTK1} + class procedure SetCallbacks(const AGtkWidget: PGtkWidget; const AWidgetInfo: PWidgetInfo); virtual; + class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override; class function GetSelStart(const ACustomComboBox: TCustomComboBox): integer; override; class function GetSelLength(const ACustomComboBox: TCustomComboBox): integer; override; class function GetItemIndex(const ACustomComboBox: TCustomComboBox): integer; override; @@ -117,6 +119,8 @@ type protected public {$IFDEF GTK1} + class procedure SetCallbacks(const AGtkWidget: PGtkWidget; const AWidgetInfo: PWidgetInfo); virtual; + class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override; class function GetIndexAtY(const ACustomListBox: TCustomListBox; y: integer): integer; override; class function GetItemIndex(const ACustomListBox: TCustomListBox): integer; override; class function GetItemRect(const ACustomListBox: TCustomListBox; Index: integer; var ARect: TRect): boolean; override; @@ -176,7 +180,7 @@ type protected public {$ifdef GTK1} - class function CreateHandle(const AWinControl: TWinControl; + class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override; class procedure AppendText(const ACustomMemo: TCustomMemo; const AText: string); override; @@ -433,7 +437,51 @@ begin end; { TGtkWSCustomListBox } + {$IFDEF GTK1} +class procedure TGtkWSCustomListBox.SetCallbacks(const AGtkWidget: PGtkWidget; + const AWidgetInfo: PWidgetInfo); +begin + TGtkWSWinControl.SetCallbacks(PGtkObject(AGtkWidget), TComponent(AWidgetInfo^.LCLObject)); + TGtkWidgetset(Widgetset).SetCallback(LM_SELCHANGE, PGtkObject(AGtkWidget), AWidgetInfo^.LCLObject); +end; + +class function TGtkWSCustomListBox.CreateHandle(const AWinControl: TWinControl; + const AParams: TCreateParams): TLCLIntfHandle; +var + Widget: PGtkWidget; + WidgetInfo: PWidgetInfo; + ScrolledWnd: PGtkScrolledWindow absolute Widget; + ListBox: TCustomListBox absolute AWinControl; + List: Pointer; +begin + Widget := gtk_scrolled_window_new(nil, nil); + GTK_WIDGET_UNSET_FLAGS(ScrolledWnd^.hscrollbar, GTK_CAN_FOCUS); + GTK_WIDGET_UNSET_FLAGS(ScrolledWnd^.vscrollbar, GTK_CAN_FOCUS); + gtk_scrolled_window_set_policy(ScrolledWnd, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_widget_show(Widget); + + List := gtk_list_new; + gtk_scrolled_window_add_with_viewport(ScrolledWnd, List); + gtk_container_set_focus_vadjustment(List, + gtk_scrolled_window_get_vadjustment(ScrolledWnd)); + gtk_container_set_focus_hadjustment(PGtkContainer(List), + gtk_scrolled_window_get_hadjustment(ScrolledWnd)); + gtk_widget_show(List); + + WidgetInfo := CreateWidgetInfo(Widget, AWinControl, AParams); + SetMainWidget(Widget, List); + WidgetInfo^.CoreWidget := List; + + TGtkWidgetSet(WidgetSet).SetSelectionMode(AWinControl, Widget, + ListBox.MultiSelect, ListBox.ExtendedSelect); + + Result := TLCLIntfHandle(PtrUInt(Widget)); + {$IFDEF DebugLCLComponents} + DebugGtkWidgets.MarkCreated(Widget, dbgsName(AWinControl)); + {$ENDIF} + SetCallbacks(Widget, WidgetInfo); +end; class function TGtkWSCustomListBox.GetIndexAtY( const ACustomListBox: TCustomListBox; y: integer): integer; @@ -816,7 +864,74 @@ end; { TGtkWSCustomComboBox } + {$IFDEF GTK1} +class procedure TGtkWSCustomComboBox.SetCallbacks(const AGtkWidget: PGtkWidget; + const AWidgetInfo: PWidgetInfo); +begin + TGtkWSWinControl.SetCallbacks(PGtkObject(AGtkWidget), TComponent(AWidgetInfo^.LCLObject)); + with TGtkWidgetset(Widgetset) do + begin + SetCallback(LM_CHANGED, PGtkObject(AGtkWidget), AWidgetInfo^.LCLObject); + SetCallback(LM_COMMAND, PGtkObject(AGtkWidget), AWidgetInfo^.LCLObject); + SetCallback(LM_SELCHANGE, PGtkObject(AGtkWidget), AWidgetInfo^.LCLObject); + end; +end; + +class function TGtkWSCustomComboBox.CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; +var + ComboBox: TComboBox absolute AWinControl; + Widget: PGtkWidget; + WidgetInfo: PWidgetInfo; + ComboWidget: PGtkCombo absolute Widget; + + ItemList: TGtkListStringList; + GtkList: PGtkList; + Allocation: TGtkAllocation; +begin + Widget := gtk_combo_new(); + + SetMainWidget(Widget, ComboWidget^.entry); + + gtk_combo_disable_activate(ComboWidget); + gtk_combo_set_case_sensitive(ComboWidget, GdkTrue); + + // Prevents the OnSelect event be fired after inserting the first item + // or deleting the selected item + GtkList:=PGtkList(ComboWidget^.List); + if GtkList^.selection = nil then + gtk_list_set_selection_mode(GtkList, GTK_SELECTION_SINGLE) + else + gtk_list_set_selection_mode(GtkList, GTK_SELECTION_BROWSE); + + // Items + ItemList:= TGtkListStringList.Create(GtkList, ComboBox, False); + gtk_object_set_data(PGtkObject(Widget), GtkListItemLCLListTag, ItemList); + ItemList.Assign(ComboBox.Items); + ItemList.Sorted:= ComboBox.Sorted; + + // ItemIndex + if ComboBox.ItemIndex >= 0 then + gtk_list_select_item(GtkList, ComboBox.ItemIndex); + + // MaxLength + gtk_entry_set_max_length(PGtkEntry(ComboWidget^.entry),guint16(ComboBox.MaxLength)); + + {$IFDEF DebugLCLComponents} + DebugGtkWidgets.MarkCreated(Widget, dbgsName(AWinControl)); + {$ENDIF} + Result := THandle(PtrUInt(Widget)); + WidgetInfo := CreateWidgetInfo(Widget, AWinControl, AParams); + + Allocation.X := AParams.X; + Allocation.Y := AParams.Y; + Allocation.Width := AParams.Width; + Allocation.Height := AParams.Height; + gtk_widget_size_allocate(PGtkWidget(Result), @Allocation); + + SetCallbacks(Widget, WidgetInfo); +end; + class function TGtkWSCustomComboBox.GetSelStart( const ACustomComboBox: TCustomComboBox): integer; begin @@ -1786,7 +1901,7 @@ var Widget: PGtkWidget; border_width: Integer; begin - Widget:=PGtkWidget(AWinControl.Handle); + Widget := PGtkWidget(AWinControl.Handle); PreferredWidth := (gtk_widget_get_xthickness(Widget)) * 2 {$ifdef gtk1} diff --git a/lcl/interfaces/gtk2/gtk2int.pas b/lcl/interfaces/gtk2/gtk2int.pas index ffdb6dfd4d..1cb9007718 100644 --- a/lcl/interfaces/gtk2/gtk2int.pas +++ b/lcl/interfaces/gtk2/gtk2int.pas @@ -55,31 +55,16 @@ type { TGtk2WidgetSet } TGtk2WidgetSet = class(TGtkWidgetSet) - private - function CreateCListBox(Sender: TObject): PGtkWidget; - function CreateListBox(Sender: TObject): PGtkWidget; protected procedure AppendText(Sender: TObject; Str: PChar); - function CreateComponentWidget(Sender: TObject; ACompStyle: Integer; - const ACaption: String): PGtkWidget; override; // temporary solution till all are created through createhandle - + procedure HookSignals(const AGTKObject: PGTKObject; const ALCLObject: TObject); override; // temporary function GetText(Sender: TComponent; var Text: String): Boolean; - procedure HookSignals(const AGTKObject: PGTKObject; const ALCLObject: TObject); override; function LoadStockPixmap(StockID: longint; var Mask: HBitmap) : HBitmap; override; procedure SetCallbackEx(const AMsg: LongInt; const AGTKObject: PGTKObject; const ALCLObject: TObject; Direct: boolean);override; procedure SetSelectionMode(Sender: TObject; Widget: PGtkWidget; MultiSelect, ExtendedSelect: boolean); override; - procedure InitializeFileDialog(FileDialog: TFileDialog; - var SelWidget: PGtkWidget; Title: PChar); override; - function CreateOpenDialogFilter(OpenDialog: TOpenDialog; - SelWidget: PGtkWidget): string; override; - procedure InitializeOpenDialog(OpenDialog: TOpenDialog; - SelWidget: PGtkWidget); override; - procedure CreatePreviewDialogControl( - PreviewDialog: TPreviewFileDialog; SelWidget: PGtkWidget); override; - function CreateThemeServices: TThemeServices; override; function GetDeviceContextClass: TGtkDeviceContextClass; override; public @@ -167,7 +152,7 @@ uses Gtk2WSControls, // Gtk2WSDbCtrls, // Gtk2WSDBGrids, -// Gtk2WSDialogs, + Gtk2WSDialogs, // Gtk2WSDirSel, // Gtk2WSEditBtn, Gtk2WSExtCtrls, diff --git a/lcl/interfaces/gtk2/gtk2widgetset.inc b/lcl/interfaces/gtk2/gtk2widgetset.inc index 56f4e18c1e..f461d92330 100644 --- a/lcl/interfaces/gtk2/gtk2widgetset.inc +++ b/lcl/interfaces/gtk2/gtk2widgetset.inc @@ -127,108 +127,7 @@ begin Result := False; end; -procedure Gtk2FileChooserNotifyCB(dialog: PGObject; pspec: PGParamSpec; - user_data: gpointer); cdecl; -var - TheDialog: TFileDialog; - GtkFilter: PGtkFileFilter; - GtkFilterList: PGSList; - NewFilterIndex: Integer; -begin - //DebugLn(['Gtk2FileChooserNotifyCB ']); - if pspec^.name = 'filter' then - begin // filter changed - theDialog := TFileDialog(user_data); - GtkFilter := gtk_file_chooser_get_filter(dialog); - GtkFilterList := gtk_file_chooser_list_filters(dialog); - NewFilterIndex := g_slist_index(GtkFilterList, GtkFilter); - theDialog.IntfFileTypeChanged(NewFilterIndex + 1); - g_slist_free(GtkFilterList); - end; -end; - -procedure Gtk2FileChooserResponseCB(widget: PGtkFileChooser; arg1: gint; - data: gpointer); cdecl; - - procedure AddFile(List: TStrings; const NewFile: string); - var - i: Integer; - begin - for i:=0 to List.Count-1 do - if List[i]=NewFile then exit; - List.Add(NewFile); - end; - -var - TheDialog: TFileDialog; - cFilename: PChar; - cFilenames: PGSList; - cFilenames1: PGSList; - Files: TStringList; -begin - //DebugLn(['Gtk2FileChooserResponseCB ']); - theDialog := TFileDialog(data); - - if arg1 = GTK_RESPONSE_CANCEL then begin - TheDialog.UserChoice := mrCancel; - Exit; - end; - - if theDialog is TOpenDialog then begin - if ofAllowMultiSelect in TOpenDialog(theDialog).Options then begin - TheDialog.FileName := ''; - Files := TStringList(TheDialog.Files); - Files.Clear; - - cFilenames := gtk_file_chooser_get_filenames(widget); - if Assigned(cFilenames) then begin - - cFilenames1 := cFilenames; - while Assigned(cFilenames1) do begin - cFilename := PChar(cFilenames1^.data); - - if Assigned(cFilename) then begin - AddFile(Files, cFilename); - g_free(cFilename); - end; - - cFilenames1 := cFilenames1^.next; - end; - - g_slist_free(cFilenames); - end; - end; - end; - - cFilename := gtk_file_chooser_get_filename(widget); - if Assigned(cFilename) then begin - TheDialog.FileName := cFilename; - g_free(cFilename); - end; - - //?? StoreCommonDialogSetup(theDialog); - theDialog.UserChoice := mrOK; -end; - -procedure gtkFileChooserSelectionChangedCB(Chooser: PGtkFileChooser; - Data: Pointer); cdecl; -var - cFilename: Pgchar; - theDialog: TFileDialog; -begin - //DebugLn(['gtkFileChooserSelectionChangedCB ']); - cFilename := gtk_file_chooser_get_filename(Chooser); - theDialog:=TFileDialog(Data); - try - if theDialog is TOpenDialog then - UpdateDetailView(TOpenDialog(theDialog)); - finally - if Assigned(cFilename) then - g_free(cFilename); - end; -end; - -Procedure gtk_clb_toggle(cellrenderertoggle : PGtkCellRendererToggle; arg1 : PGChar; +procedure gtk_clb_toggle(cellrenderertoggle : PGtkCellRendererToggle; arg1 : PGChar; WinControl: TWinControl); cdecl; var aWidget : PGTKWidget; @@ -669,217 +568,6 @@ begin end; *) -{------------------------------------------------------------------------------ - Function: TGtk2WidgetSet.InitializeOpenDialog - Params: OpenDialog: TOpenDialog; SelWidget: PGtkWidget - Returns: - - - Adds some functionality to a gtk file selection dialog. - - multiselection - - range selection - - close on escape - - file information - - history pulldown - - filter pulldown - - preview control - - requires: gtk+ 2.6 - ------------------------------------------------------------------------------} -procedure TGtk2WidgetSet.InitializeOpenDialog(OpenDialog: TOpenDialog; - SelWidget: PGtkWidget); -var - FileSelWidget: PGtkFileChooser; - HelpButton: PGtkWidget; - InitialFilename: String; - //FrameWidget: PGtkWidget; - //HBox: PGtkWidget; - //FileDetailLabel: PGtkWidget; -begin - FileSelWidget := GTK_FILE_CHOOSER(SelWidget); - - // Help button - if (ofShowHelp in OpenDialog.Options) then begin - HelpButton := gtk_dialog_add_button(FileSelWidget, GTK_STOCK_HELP, GTK_RESPONSE_NONE); - - g_signal_connect( gtk_object(HelpButton), - 'clicked', gtk_signal_func(@gtkDialogHelpclickedCB), OpenDialog); - end; - - if ofAllowMultiSelect in OpenDialog.Options then - gtk_file_chooser_set_select_multiple(FileSelWidget, True); - - // History List - a frame with an option menu - CreateOpenDialogHistory(OpenDialog, SelWidget); - - // Filter - CreateOpenDialogFilter(OpenDialog,SelWidget); - - // connect change event - g_signal_connect( gtk_object(FileSelWidget), - 'selection-changed', gtk_signal_func(@gtkFileChooserSelectionChangedCB), - OpenDialog); - - (* TODO - // Details - a frame with a label - if (ofViewDetail in OpenDialog.Options) then begin - - // create the frame around the information - FrameWidget:=gtk_frame_new(PChar(rsFileInformation)); - //gtk_box_pack_start(GTK_BOX(FileSelWidget^.main_vbox), - // FrameWidget,false,false,0); - gtk_box_pack_start(GTK_BOX(gtk_file_chooser_get_extra_widget( - PGtkFileChooser(SelWidget))), FrameWidget,false,false,0); - gtk_widget_show(FrameWidget); - // create a HBox, so that the information is left justified - HBox:=gtk_hbox_new(false,0); - gtk_container_add(GTK_CONTAINER(FrameWidget), HBox); - // create the label for the file information - FileDetailLabel:=gtk_label_new(PChar(rsDefaultFileInfoValue)); - gtk_box_pack_start(GTK_BOX(HBox),FileDetailLabel,false,false,5); - gtk_widget_show_all(HBox); - end else - FileDetailLabel:=nil; - gtk_object_set_data(PGtkObject(SelWidget), 'FileDetailLabel', - FileDetailLabel); - *) - // preview - if (OpenDialog is TPreviewFileDialog) then - CreatePreviewDialogControl(TPreviewFileDialog(OpenDialog), SelWidget); - - // set initial filename (gtk expects an absolute filename) - InitialFilename:=TrimFilename(OpenDialog.Filename); - if InitialFilename<>'' then begin - if (not FilenameIsAbsolute(InitialFilename)) - and (OpenDialog.InitialDir<>'') then - InitialFilename:=TrimFilename(OpenDialog.InitialDir+PathDelim+InitialFilename); - if not FilenameIsAbsolute(InitialFilename) then - InitialFilename:=CleanAndExpandFilename(InitialFilename); - gtk_file_chooser_set_filename(FileSelWidget,PChar(InitialFilename)); - end; - - //if InitialFilter <> 'none' then - // PopulateFileAndDirectoryLists(FileSelWidget, InitialFilter); -end; - -{------------------------------------------------------------------------------ - Function: TGtk2WidgetSet.InitializeFileDialog - Params: FileDialog: TFileDialog; var SelWidget: PGtkWidget - Returns: - - - Creates a new TFile/Open/SaveDialog - requires: gtk+ 2.6 - ------------------------------------------------------------------------------} -procedure TGtk2WidgetSet.InitializeFileDialog(FileDialog: TFileDialog; - var SelWidget: PGtkWidget; Title: PChar); -var - Action: TGtkFileChooserAction; - Button1: String; -begin - Action := GTK_FILE_CHOOSER_ACTION_OPEN; - Button1 := GTK_STOCK_OPEN; - - if (FileDialog is TSaveDialog) or (FileDialog is TSavePictureDialog) then begin - Action := GTK_FILE_CHOOSER_ACTION_SAVE; - Button1 := GTK_STOCK_SAVE; - end - else if FileDialog is TSelectDirectoryDialog then begin - Action := GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; - Button1 := GTK_STOCK_OPEN; - end; - - SelWidget := gtk_file_chooser_dialog_new(Title, nil, Action, - PChar(GTK_STOCK_CANCEL), [GTK_RESPONSE_CANCEL, PChar(Button1), GTK_RESPONSE_OK, nil]); - - g_signal_connect(SelWidget, 'response', gtk_signal_func(@Gtk2FileChooserResponseCB), FileDialog); - g_signal_connect(SelWidget, 'notify', gtk_signal_func(@Gtk2FileChooserNotifyCB), FileDialog); - -(*gtk 2.8 - if FileDialog is TSaveDialog then begin - gtk_file_chooser_set_do_overwrite_confirmation(SelWidget, - ofOverwritePrompt in TOpenDialog(theDialog).Options); - end; -*) - if FileDialog.InitialDir <> '' then - gtk_file_chooser_set_current_folder (SelWidget, pgChar( FileDialog.InitialDir) ); - - if FileDialog is TOpenDialog then - InitializeOpenDialog(TOpenDialog(FileDialog), SelWidget); - - if FileDialog.InheritsFrom(TSaveDialog) then begin - if FileDialog.InitialDir <> '' then - gtk_file_chooser_set_current_folder (SelWidget, PChar(FileDialog.InitialDir)); - end; - - if gtk_file_chooser_get_action(SelWidget) in - [GTK_FILE_CHOOSER_ACTION_SAVE,GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER] - then - gtk_file_chooser_set_current_name (SelWidget, pgChar( FileDialog.FileName) ); - - InitializeCommonDialog(TCommonDialog(FileDialog), SelWidget); -end; - -function TGtk2WidgetSet.CreateOpenDialogFilter(OpenDialog: TOpenDialog; - SelWidget: PGtkWidget): string; -var - FilterList: TFPList; - i, j, k: integer; - GtkFilter: PGtkFileFilter; - MaskList: TStringList; -begin - ExtractFilterList(OpenDialog.Filter, FilterList, false); - if FilterList.Count > 0 then begin - j := 1; - MaskList := TStringList.Create; - MaskList.Delimiter := ';'; - for i := 0 to FilterList.Count-1 do begin - GtkFilter := gtk_file_filter_new(); - - MaskList.DelimitedText := PFileSelFilterEntry(FilterList[i])^.Mask; - - for k := 0 to MaskList.Count-1 do - gtk_file_filter_add_pattern(GtkFilter, PChar(MaskList.Strings[k])); - - gtk_file_filter_set_name(GtkFilter, PFileSelFilterEntry(FilterList[i])^.Description); - - gtk_file_chooser_add_filter(SelWidget, GtkFilter); - - if j = OpenDialog.FilterIndex then - gtk_file_chooser_set_filter(SelWidget, GtkFilter); - - Inc(j); - GtkFilter := nil; - end; - MaskList.Free; - end; - - gtk_object_set_data(PGtkObject(SelWidget), 'LCLFilterList', FilterList); - - Result := 'hm'; { Don't use '' as null return as this is used for *.* } -end; - -procedure TGtk2WidgetSet.CreatePreviewDialogControl( - PreviewDialog: TPreviewFileDialog; SelWidget: PGtkWidget); -var - PreviewWidget: PGtkWidget; - AControl: TPreviewFileControl; - FileChooser: PGtkFileChooser; -begin - AControl := PreviewDialog.PreviewFileControl; - if AControl = nil then Exit; - - FileChooser := PGtkFileChooser(SelWidget); - - PreviewWidget := PGtkWidget(AControl.Handle); - - gtk_object_set_data(PGtkObject(PreviewWidget),'LCLPreviewFixed', - PreviewWidget); - gtk_widget_set_size_request(PreviewWidget,AControl.Width,AControl.Height); - - gtk_file_chooser_set_preview_widget(FileChooser, PreviewWidget); - - gtk_widget_show(PreviewWidget); -end; - function TGtk2WidgetSet.CreateThemeServices: TThemeServices; begin Result := TGtk2ThemeServices.Create; @@ -893,46 +581,6 @@ begin G_CALLBACK (@gtk_commit_cb), nil); end; -function TGtk2WidgetSet.CreateCListBox(Sender: TObject): PGtkWidget; -var - ScrolledWnd: PGtkScrolledWindow absolute Result; -begin - Result := gtk_scrolled_window_new(nil, nil);//give something just in case - GTK_WIDGET_UNSET_FLAGS(ScrolledWnd^.hscrollbar, GTK_CAN_FOCUS); - GTK_WIDGET_UNSET_FLAGS(ScrolledWnd^.vscrollbar, GTK_CAN_FOCUS); - gtk_scrolled_window_set_policy(ScrolledWnd, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_widget_show(Result); - - DebugLn('TODO: TGtkWidgetSet.CreateComponent csCListBox'); -end; - -function TGtk2WidgetSet.CreateComponentWidget(Sender: TObject; ACompStyle: Integer; const ACaption: String): PGtkWidget; -begin - case ACompstyle of - csListBox, csCheckListBox: - Result := CreateListBox(Sender); - - csCListBox: - Result := CreateCListBox(Sender); - - else - Result := inherited CreateComponentWidget(Sender, ACompStyle, ACaption); - end; -end; - -function TGtk2WidgetSet.CreateListBox(Sender: TObject): PGtkWidget; -var - ScrolledWnd: PGtkScrolledWindow absolute Result; -begin - Result := gtk_scrolled_window_new(nil, nil);//give something just in case - GTK_WIDGET_UNSET_FLAGS(ScrolledWnd^.hscrollbar, GTK_CAN_FOCUS); - GTK_WIDGET_UNSET_FLAGS(ScrolledWnd^.vscrollbar, GTK_CAN_FOCUS); - gtk_scrolled_window_set_policy(ScrolledWnd, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_widget_show(Result); - - DebugLn('TODO: TGtkWidgetSet.CreateComponent csListBox, csCheckListBox'); -end; - destructor TGtk2WidgetSet.Destroy; begin g_object_unref(im_context); diff --git a/lcl/interfaces/gtk2/gtk2wsdialogs.pp b/lcl/interfaces/gtk2/gtk2wsdialogs.pp index b6f1cdb3bc..de6e4af657 100644 --- a/lcl/interfaces/gtk2/gtk2wsdialogs.pp +++ b/lcl/interfaces/gtk2/gtk2wsdialogs.pp @@ -33,15 +33,16 @@ uses // To get as little as posible circles, // uncomment only when needed for registration //////////////////////////////////////////////////// -// Dialogs, + Gtk2, Glib2, gdk2, pango, + SysUtils, Classes, + Controls, Dialogs, ExtDlgs, + GtkWSDialogs, GtkInt, GtkGlobals, GtkDef, GtkProc, //////////////////////////////////////////////////// - LCLType, WSDialogs, WSLCLClasses; - + LCLType, WSDialogs, WSLCLClasses, FileUtil; type - { TGtk2WSCommonDialog } - TGtk2WSCommonDialog = class(TWSCommonDialog) + TGtk2WSCommonDialog = class(TGtkWSCommonDialog) private protected public @@ -49,23 +50,28 @@ type { TGtk2WSFileDialog } - TGtk2WSFileDialog = class(TWSFileDialog) + TGtk2WSFileDialog = class(TGtkWSFileDialog) private protected + class procedure SetCallbacks(const AGtkWidget: PGtkWidget; const AWidgetInfo: PWidgetInfo); override; public + class function CreateHandle(const ACommonDialog: TCommonDialog): THandle; override; end; { TGtk2WSOpenDialog } - TGtk2WSOpenDialog = class(TWSOpenDialog) + TGtk2WSOpenDialog = class(TGtkWSOpenDialog) private protected + class function CreateOpenDialogFilter(OpenDialog: TOpenDialog; SelWidget: PGtkWidget): string; override; + class procedure CreatePreviewDialogControl(PreviewDialog: TPreviewFileDialog; SelWidget: PGtkWidget); override; public + class function CreateHandle(const ACommonDialog: TCommonDialog): THandle; override; end; { TGtk2WSSaveDialog } - TGtk2WSSaveDialog = class(TWSSaveDialog) + TGtk2WSSaveDialog = class(TGtkWSSaveDialog) private protected public @@ -73,7 +79,7 @@ type { TGtk2WSSelectDirectoryDialog } - TGtk2WSSelectDirectoryDialog = class(TWSSelectDirectoryDialog) + TGtk2WSSelectDirectoryDialog = class(TGtkWSSelectDirectoryDialog) private protected public @@ -81,7 +87,7 @@ type { TGtk2WSColorDialog } - TGtk2WSColorDialog = class(TWSColorDialog) + TGtk2WSColorDialog = class(TGtkWSColorDialog) private protected public @@ -89,7 +95,7 @@ type { TGtk2WSColorButton } - TGtk2WSColorButton = class(TWSColorButton) + TGtk2WSColorButton = class(TGtkWSColorButton) private protected public @@ -97,7 +103,7 @@ type { TGtk2WSFontDialog } - TGtk2WSFontDialog = class(TWSFontDialog) + TGtk2WSFontDialog = class(TGtkWSFontDialog) private protected public @@ -106,6 +112,339 @@ type implementation +// ---------------------- signals ---------------------------------------------- + +procedure gtkFileChooserSelectionChangedCB(Chooser: PGtkFileChooser; + Data: Pointer); cdecl; +var + cFilename: Pgchar; + theDialog: TFileDialog; +begin + //DebugLn(['gtkFileChooserSelectionChangedCB ']); + cFilename := gtk_file_chooser_get_filename(Chooser); + theDialog:=TFileDialog(Data); + try + if theDialog is TOpenDialog then + UpdateDetailView(TOpenDialog(theDialog)); + finally + if Assigned(cFilename) then + g_free(cFilename); + end; +end; + +procedure Gtk2FileChooserResponseCB(widget: PGtkFileChooser; arg1: gint; + data: gpointer); cdecl; + + procedure AddFile(List: TStrings; const NewFile: string); + var + i: Integer; + begin + for i := 0 to List.Count-1 do + if List[i] = NewFile then + Exit; + List.Add(NewFile); + end; + +var + TheDialog: TFileDialog; + cFilename: PChar; + cFilenames: PGSList; + cFilenames1: PGSList; + Files: TStringList; +begin + //DebugLn(['Gtk2FileChooserResponseCB ']); + theDialog := TFileDialog(data); + + if arg1 = GTK_RESPONSE_CANCEL then + begin + TheDialog.UserChoice := mrCancel; + Exit; + end; + + if theDialog is TOpenDialog then + begin + if ofAllowMultiSelect in TOpenDialog(theDialog).Options then + begin + TheDialog.FileName := ''; + Files := TStringList(TheDialog.Files); + Files.Clear; + cFilenames := gtk_file_chooser_get_filenames(widget); + if Assigned(cFilenames) then + begin + cFilenames1 := cFilenames; + while Assigned(cFilenames1) do + begin + cFilename := PChar(cFilenames1^.data); + if Assigned(cFilename) then + begin + AddFile(Files, cFilename); + g_free(cFilename); + end; + cFilenames1 := cFilenames1^.next; + end; + g_slist_free(cFilenames); + end; + end; + end; + + cFilename := gtk_file_chooser_get_filename(widget); + if Assigned(cFilename) then + begin + TheDialog.FileName := cFilename; + g_free(cFilename); + end; + + //?? StoreCommonDialogSetup(theDialog); + theDialog.UserChoice := mrOK; +end; + +procedure Gtk2FileChooserNotifyCB(dialog: PGObject; pspec: PGParamSpec; + user_data: gpointer); cdecl; +var + TheDialog: TFileDialog; + GtkFilter: PGtkFileFilter; + GtkFilterList: PGSList; + NewFilterIndex: Integer; +begin + //DebugLn(['Gtk2FileChooserNotifyCB ']); + if pspec^.name = 'filter' then + begin // filter changed + theDialog := TFileDialog(user_data); + GtkFilter := gtk_file_chooser_get_filter(dialog); + GtkFilterList := gtk_file_chooser_list_filters(dialog); + NewFilterIndex := g_slist_index(GtkFilterList, GtkFilter); + theDialog.IntfFileTypeChanged(NewFilterIndex + 1); + g_slist_free(GtkFilterList); + end; +end; + +// ---------------------- END OF signals --------------------------------------- + +{ TGtk2WSOpenDialog } + +class function TGtk2WSOpenDialog.CreateOpenDialogFilter( + OpenDialog: TOpenDialog; SelWidget: PGtkWidget): string; +var + FilterList: TFPList; + i, j, k: integer; + GtkFilter: PGtkFileFilter; + MaskList: TStringList; +begin + ExtractFilterList(OpenDialog.Filter, FilterList, false); + if FilterList.Count > 0 then + begin + j := 1; + MaskList := TStringList.Create; + MaskList.Delimiter := ';'; + for i := 0 to FilterList.Count-1 do + begin + GtkFilter := gtk_file_filter_new(); + + MaskList.DelimitedText := PFileSelFilterEntry(FilterList[i])^.Mask; + + for k := 0 to MaskList.Count-1 do + gtk_file_filter_add_pattern(GtkFilter, PChar(MaskList.Strings[k])); + + gtk_file_filter_set_name(GtkFilter, PFileSelFilterEntry(FilterList[i])^.Description); + + gtk_file_chooser_add_filter(SelWidget, GtkFilter); + + if j = OpenDialog.FilterIndex then + gtk_file_chooser_set_filter(SelWidget, GtkFilter); + + Inc(j); + GtkFilter := nil; + end; + MaskList.Free; + end; + + gtk_object_set_data(PGtkObject(SelWidget), 'LCLFilterList', FilterList); + + Result := 'hm'; { Don't use '' as null return as this is used for *.* } +end; + +class procedure TGtk2WSOpenDialog.CreatePreviewDialogControl( + PreviewDialog: TPreviewFileDialog; SelWidget: PGtkWidget); +var + PreviewWidget: PGtkWidget; + AControl: TPreviewFileControl; + FileChooser: PGtkFileChooser; +begin + AControl := PreviewDialog.PreviewFileControl; + if AControl = nil then Exit; + + FileChooser := PGtkFileChooser(SelWidget); + + PreviewWidget := PGtkWidget(AControl.Handle); + + gtk_object_set_data(PGtkObject(PreviewWidget),'LCLPreviewFixed', + PreviewWidget); + gtk_widget_set_size_request(PreviewWidget,AControl.Width,AControl.Height); + + gtk_file_chooser_set_preview_widget(FileChooser, PreviewWidget); + + gtk_widget_show(PreviewWidget); +end; + +{ + Adds some functionality to a gtk file selection dialog. + - multiselection + - range selection + - close on escape + - file information + - history pulldown + - filter pulldown + - preview control + + requires: gtk+ 2.6 +} +class function TGtk2WSOpenDialog.CreateHandle(const ACommonDialog: TCommonDialog): THandle; +var + FileSelWidget: PGtkFileChooser; + OpenDialog: TOpenDialog absolute ACommonDialog; + HelpButton: PGtkWidget; + InitialFilename: String; + //FrameWidget: PGtkWidget; + //HBox: PGtkWidget; + //FileDetailLabel: PGtkWidget; +begin + Result := TGtk2WSFileDialog.CreateHandle(ACommonDialog); + FileSelWidget := PGtkFileChooser(Result); + + if OpenDialog.InheritsFrom(TSaveDialog) then + begin + if OpenDialog.InitialDir <> '' then + gtk_file_chooser_set_current_folder(FileSelWidget, Pgchar(OpenDialog.InitialDir)); + end; + + // Help button + if (ofShowHelp in OpenDialog.Options) then + begin + HelpButton := gtk_dialog_add_button(FileSelWidget, GTK_STOCK_HELP, GTK_RESPONSE_NONE); + + g_signal_connect(PGtkObject(HelpButton), + 'clicked', gtk_signal_func(@gtkDialogHelpclickedCB), OpenDialog); + end; + + if ofAllowMultiSelect in OpenDialog.Options then + gtk_file_chooser_set_select_multiple(FileSelWidget, True); + + // History List - a frame with an option menu + CreateOpenDialogHistory(OpenDialog, FileSelWidget); + + // Filter + CreateOpenDialogFilter(OpenDialog, FileSelWidget); + + // connect change event + g_signal_connect(PGtkObject(FileSelWidget), + 'selection-changed', gtk_signal_func(@gtkFileChooserSelectionChangedCB), + OpenDialog); + + (* TODO + // Details - a frame with a label + if (ofViewDetail in OpenDialog.Options) then begin + + // create the frame around the information + FrameWidget:=gtk_frame_new(PChar(rsFileInformation)); + //gtk_box_pack_start(GTK_BOX(FileSelWidget^.main_vbox), + // FrameWidget,false,false,0); + gtk_box_pack_start(GTK_BOX(gtk_file_chooser_get_extra_widget( + PGtkFileChooser(SelWidget))), FrameWidget,false,false,0); + gtk_widget_show(FrameWidget); + // create a HBox, so that the information is left justified + HBox:=gtk_hbox_new(false,0); + gtk_container_add(GTK_CONTAINER(FrameWidget), HBox); + // create the label for the file information + FileDetailLabel:=gtk_label_new(PChar(rsDefaultFileInfoValue)); + gtk_box_pack_start(GTK_BOX(HBox),FileDetailLabel,false,false,5); + gtk_widget_show_all(HBox); + end else + FileDetailLabel:=nil; + gtk_object_set_data(PGtkObject(SelWidget), 'FileDetailLabel', + FileDetailLabel); + *) + // preview + if (OpenDialog is TPreviewFileDialog) then + CreatePreviewDialogControl(TPreviewFileDialog(OpenDialog), PGtkWidget(FileSelWidget)); + + // set initial filename (gtk expects an absolute filename) + InitialFilename := TrimFilename(OpenDialog.Filename); + if InitialFilename <> '' then + begin + if not FilenameIsAbsolute(InitialFilename) and (OpenDialog.InitialDir <> '') then + InitialFilename := TrimFilename(OpenDialog.InitialDir + PathDelim + InitialFilename); + if not FilenameIsAbsolute(InitialFilename) then + InitialFilename := CleanAndExpandFilename(InitialFilename); + gtk_file_chooser_set_filename(FileSelWidget, PChar(InitialFilename)); + end; + + //if InitialFilter <> 'none' then + // PopulateFileAndDirectoryLists(FileSelWidget, InitialFilter); +end; + +{ TGtk2WSFileDialog } + +class procedure TGtk2WSFileDialog.SetCallbacks(const AGtkWidget: PGtkWidget; + const AWidgetInfo: PWidgetInfo); +begin + TGtkWSCommonDialog.SetCallbacks(AGtkWidget, AWidgetInfo); + g_signal_connect(AGtkWidget, 'response', gtk_signal_func(@Gtk2FileChooserResponseCB), AWidgetInfo^.LCLObject); + g_signal_connect(AGtkWidget, 'notify', gtk_signal_func(@Gtk2FileChooserNotifyCB), AWidgetInfo^.LCLObject); +end; + +{ + Creates a new TFile/Open/SaveDialog + requires: gtk+ 2.6 +} +class function TGtk2WSFileDialog.CreateHandle(const ACommonDialog: TCommonDialog + ): THandle; +var + FileDialog: TFileDialog absolute ACommonDialog; + Action: TGtkFileChooserAction; + Button1: String; + Widget: PGtkWidget; + WidgetInfo: PWidgetInfo; +begin + Action := GTK_FILE_CHOOSER_ACTION_OPEN; + Button1 := GTK_STOCK_OPEN; + + if (FileDialog is TSaveDialog) or (FileDialog is TSavePictureDialog) then + begin + Action := GTK_FILE_CHOOSER_ACTION_SAVE; + Button1 := GTK_STOCK_SAVE; + end + else + if FileDialog is TSelectDirectoryDialog then + begin + Action := GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; + Button1 := GTK_STOCK_OPEN; + end; + + Widget := gtk_file_chooser_dialog_new(PChar(FileDialog.Title), nil, Action, + PChar(GTK_STOCK_CANCEL), [GTK_RESPONSE_CANCEL, PChar(Button1), GTK_RESPONSE_OK, nil]); + +(*gtk 2.8 + if FileDialog is TSaveDialog then + begin + gtk_file_chooser_set_do_overwrite_confirmation(Widget, + ofOverwritePrompt in TOpenDialog(theDialog).Options); + end; +*) + if FileDialog.InitialDir <> '' then + gtk_file_chooser_set_current_folder(Widget, Pgchar(FileDialog.InitialDir)); + + if gtk_file_chooser_get_action(Widget) in + [GTK_FILE_CHOOSER_ACTION_SAVE, GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER] + then + gtk_file_chooser_set_current_name(Widget, Pgchar(FileDialog.FileName)); + + Result := THandle(PtrUInt(Widget)); + WidgetInfo := CreateWidgetInfo(Widget); + WidgetInfo^.LCLObject := ACommonDialog; + TGtkWSCommonDialog.SetSizes(Widget, WidgetInfo); + SetCallbacks(Widget, WidgetInfo); +end; + initialization //////////////////////////////////////////////////// @@ -115,8 +454,8 @@ initialization // which actually implement something //////////////////////////////////////////////////// // RegisterWSComponent(TCommonDialog, TGtk2WSCommonDialog); -// RegisterWSComponent(TFileDialog, TGtk2WSFileDialog); -// RegisterWSComponent(TOpenDialog, TGtk2WSOpenDialog); + RegisterWSComponent(TFileDialog, TGtk2WSFileDialog); + RegisterWSComponent(TOpenDialog, TGtk2WSOpenDialog); // RegisterWSComponent(TSaveDialog, TGtk2WSSaveDialog); // RegisterWSComponent(TSelectDirectoryDialog, TGtk2WSSelectDirectoryDialog); // RegisterWSComponent(TColorDialog, TGtk2WSColorDialog); diff --git a/lcl/interfaces/qt/qtint.pp b/lcl/interfaces/qt/qtint.pp index d9b4d51e8c..ed29e1a4e3 100644 --- a/lcl/interfaces/qt/qtint.pp +++ b/lcl/interfaces/qt/qtint.pp @@ -101,7 +101,6 @@ type function InitHintFont(HintFont: TObject): Boolean; override; // create and destroy - function CreateComponent(Sender : TObject): THandle; override; // deprecated function CreateTimer(Interval: integer; TimerFunc: TFNTimerProc): THandle; override; function DestroyTimer(TimerHandle: THandle): boolean; override; diff --git a/lcl/interfaces/qt/qtobject.inc b/lcl/interfaces/qt/qtobject.inc index 8279cebc34..4c626271fe 100644 --- a/lcl/interfaces/qt/qtobject.inc +++ b/lcl/interfaces/qt/qtobject.inc @@ -328,18 +328,6 @@ begin Result := False; end; -{------------------------------------------------------------------------------ - Function: TQtWidgetSet.CreateComponent - Params: sender - object for which to create visual representation - Returns: nothing - - Deprecated, never call this function - ------------------------------------------------------------------------------} -function TQtWidgetSet.CreateComponent(Sender : TObject): THandle; -begin - Result := 0; -end; - {------------------------------------------------------------------------------ Function: TQtWidgetSet.IsValidDC Params: DC - handle to a device context (TQtDeviceContext) diff --git a/lcl/interfaces/win32/win32int.pp b/lcl/interfaces/win32/win32int.pp index 8820cefa2e..266d31f996 100644 --- a/lcl/interfaces/win32/win32int.pp +++ b/lcl/interfaces/win32/win32int.pp @@ -201,7 +201,6 @@ type procedure ShowHide(Sender: TObject); // create and destroy - function CreateComponent(Sender : TObject): THandle; override; function CreateTimer(Interval: integer; TimerFunc: TFNTimerProc) : THandle; override; function DestroyTimer(TimerHandle: THandle) : boolean; override; diff --git a/lcl/interfaces/win32/win32object.inc b/lcl/interfaces/win32/win32object.inc index 3cfe13d860..cab2a45546 100644 --- a/lcl/interfaces/win32/win32object.inc +++ b/lcl/interfaces/win32/win32object.inc @@ -519,19 +519,6 @@ begin Result := TWin32ThemeServices.Create; end; - {------------------------------------------------------------------------------ - Function: TWin32WidgetSet.CreateComponent - Params: Sender - object for which to create visual representation - Returns: nothing - - Tells Windows to create a control - ------------------------------------------------------------------------------} -function TWin32WidgetSet.CreateComponent(Sender: TObject): THandle; -begin - DebugLn('WARNING: TWin32WidgetSet.CreateComponent is deprecated, should not be reachable!!'); - Result := 0; -end; - {------------------------------------------------------------------------------ Method: TWin32WidgetSet.AssignSelf Params: Window - The window to assign diff --git a/lcl/interfaces/win32/win32wscontrols.pp b/lcl/interfaces/win32/win32wscontrols.pp index d252e3f4c1..5962f438d5 100644 --- a/lcl/interfaces/win32/win32wscontrols.pp +++ b/lcl/interfaces/win32/win32wscontrols.pp @@ -189,12 +189,12 @@ begin FlagsEx := FlagsEx or WS_EX_CLIENTEDGE; SetStdBiDiModeParams(AWinControl, Params); {$IFDEF VerboseSizeMsg} - DebugLn('TWin32WidgetSet.CreateComponent A ' + dbgsName(AWinControl) + ' ' + + DebugLn('PrepareCreateWindow ' + dbgsName(AWinControl) + ' ' + Format('%d, %d, %d, %d', [Left, Top, Width, Height])); {$ENDIF} - Assert(False, Format('Trace:TWin32WidgetSet.CreateComponent - Creating component %S with the caption of %S', [AWinControl.ClassName, AWinControl.Caption])); - Assert(False, Format('Trace:TWin32WidgetSet.CreateComponent - Left: %D, Top: %D, Width: %D, Height: %D, Parent handle: 0x%X, instance handle: 0x%X', [Left, Top, Width, Height, Parent, HInstance])); + Assert(False, Format('Trace:PrepareCreateWindow - Creating component %S with the caption of %S', [AWinControl.ClassName, AWinControl.Caption])); + Assert(False, Format('Trace:PrepareCreateWindow - Left: %D, Top: %D, Width: %D, Height: %D, Parent handle: 0x%X, instance handle: 0x%X', [Left, Top, Width, Height, Parent, HInstance])); end; end; diff --git a/lcl/interfaces/wince/winceint.pp b/lcl/interfaces/wince/winceint.pp index 75e85e6573..d28a8050a7 100644 --- a/lcl/interfaces/wince/winceint.pp +++ b/lcl/interfaces/wince/winceint.pp @@ -161,7 +161,6 @@ type procedure ShowHide(Sender: TObject); // create and destroy - function CreateComponent(Sender : TObject): THandle; override; function CreateTimer(Interval: integer; TimerFunc: TFNTimerProc) : THandle; override; function DestroyTimer(TimerHandle: THandle) : boolean; override; diff --git a/lcl/interfaces/wince/winceobject.inc b/lcl/interfaces/wince/winceobject.inc index c8f9003bb2..95891c3409 100644 --- a/lcl/interfaces/wince/winceobject.inc +++ b/lcl/interfaces/wince/winceobject.inc @@ -506,11 +506,6 @@ begin end; end; -function TWinCEWidgetSet.CreateComponent(Sender: TObject): THandle; -begin - -end; - { Private methods (in no significant order) } {------------------------------------------------------------------------------ diff --git a/lcl/interfaces/wince/wincewscontrols.pp b/lcl/interfaces/wince/wincewscontrols.pp index 341c2fc8b8..2b19bf1b60 100644 --- a/lcl/interfaces/wince/wincewscontrols.pp +++ b/lcl/interfaces/wince/wincewscontrols.pp @@ -195,11 +195,11 @@ begin if TCustomControl(AWinControl).BorderStyle = bsSingle then FlagsEx := FlagsEx or WS_EX_CLIENTEDGE; {$IFDEF VerboseSizeMsg} - writeln('TWinCEWidgetSet.CreateComponent A ',AWinControl.Name,':',AWinControl.ClassName,' ',Left,',',Top,',',Width,',',Height); + writeln('PrepareCreateWindow ',AWinControl.Name,':',AWinControl.ClassName,' ',Left,',',Top,',',Width,',',Height); {$ENDIF} - //Assert(False, Format('Trace:TWinCEWidgetSet.CreateComponent - Creating component %S with the caption of %S', [AWinControl.ClassName, AWinControl.Caption])); - //Assert(False, Format('Trace:TWinCEWidgetSet.CreateComponent - Left: %D, Top: %D, Width: %D, Height: %D, Parent handle: 0x%X, instance handle: 0x%X', [Left, Top, Width, Height, Parent, HInstance])); + //Assert(False, Format('Trace:PrepareCreateWindow - Creating component %S with the caption of %S', [AWinControl.ClassName, AWinControl.Caption])); + //Assert(False, Format('Trace:PrepareCreateWindow - Left: %D, Top: %D, Width: %D, Height: %D, Parent handle: 0x%X, instance handle: 0x%X', [Left, Top, Width, Height, Parent, HInstance])); end; end; diff --git a/lcl/widgetset/wscontrols.pp b/lcl/widgetset/wscontrols.pp index 21aa781aa4..065b71957d 100644 --- a/lcl/widgetset/wscontrols.pp +++ b/lcl/widgetset/wscontrols.pp @@ -156,7 +156,7 @@ class function TWSWinControl.CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; begin // For now default to the old creation routines - Result := WidgetSet.CreateComponent(AWinControl); + Result := 0; end; class procedure TWSWinControl.DestroyHandle(const AWinControl: TWinControl);