diff options
| author | Tomas Bzatek <tbzatek@redhat.com> | 2025-01-04 20:41:26 +0100 |
|---|---|---|
| committer | Tomas Bzatek <tbzatek@redhat.com> | 2025-11-27 21:42:57 +0100 |
| commit | 90db8b6652f73ddc335922d3a7c593878d83c45e (patch) | |
| tree | 6b3f8ed57d4dc3358c2965bf41f6e613b8b80bf0 | |
| parent | 63ff1bea9bb1e87a7e2643f680d04f2b9c00d072 (diff) | |
| download | tuxcmd-90db8b6652f73ddc335922d3a7c593878d83c45e.tar.xz | |
Basic ListView CSS styling
| -rw-r--r-- | Makefile | 8 | ||||
| -rw-r--r-- | UChecksum.pas | 2 | ||||
| -rw-r--r-- | UConfig.pas | 7 | ||||
| -rw-r--r-- | UCore.pas | 22 | ||||
| -rw-r--r-- | UCoreClasses.pas | 2 | ||||
| -rw-r--r-- | UCoreUtils.pas | 120 | ||||
| -rw-r--r-- | UEngines.pas | 2 | ||||
| -rw-r--r-- | UFileAssoc.pas | 11 | ||||
| -rw-r--r-- | UFileTypeSettings.pas | 10 | ||||
| -rw-r--r-- | UMain.pas | 209 | ||||
| -rw-r--r-- | UPreferences.pas | 26 | ||||
| -rw-r--r-- | libgtk_kylix/GTKControls.pas | 38 | ||||
| -rw-r--r-- | libgtk_kylix/GTKDialogs.pas | 5 | ||||
| -rw-r--r-- | libgtk_kylix/GTKForms.pas | 109 | ||||
| -rw-r--r-- | libgtk_kylix/GTKStdCtrls.pas | 19 | ||||
| -rw-r--r-- | libgtk_kylix/GTKUtils.pas | 138 | ||||
| -rw-r--r-- | libgtk_kylix/GTKView.pas | 457 |
17 files changed, 625 insertions, 560 deletions
@@ -35,9 +35,11 @@ LIB_SUFFIX=`if test \`uname -m\` = x86_64 -o \`uname -m\` = ppc64; then echo 64; # -CR and -Cr must be disabled here, causes range check errors with gnome-power-manager # -Cg generates internal compiler errors on i386 # -XX prevents linking errors of unresolved and unused symbols +# -gc doesn't play nice with threads # "-k-z noexecstack" (with quotes as a single parameter) avoids marking stack as executable, allowing to work correctly with SELinux in Enforcing mode -CFLAGS= -vewnhib -Sch -Un -Ci -Co -XX "-k-z noexecstack" -EXTRA_CFLAGS= -O3 +# CFLAGS= -vewnhib -Sch -Un -Ci -Co -XX "-k-z noexecstack" +CFLAGS= -vewnhib -Sch -Ci -Co -CO -Cr -CR +# EXTRA_CFLAGS= -O3 tuxcmd:: @@ -53,7 +55,7 @@ tuxcmd:: tuxcmd.dpr -debug: EXTRA_CFLAGS = -g -gl -gv -O- +debug: EXTRA_CFLAGS = -g -gt -gl -gw3 -gv -O- debug: tuxcmd final_debug: EXTRA_CFLAGS = -g -gl -gv -O3 diff --git a/UChecksum.pas b/UChecksum.pas index 515ae8f..a0922d7 100644 --- a/UChecksum.pas +++ b/UChecksum.pas @@ -290,7 +290,7 @@ begin CommentOpen := False; if CommentTextView.TextBuffer.LineCount > 1 then begin s1 := ''; - for i := 1 to 50 do s1 := s1 + Chr($2212); + for i := 1 to 50 do s1 := s1 + '-' { TODO Chr($2212) }; CommentTextView.TextBuffer.InsertText(StrToUTF8(s1 + #13)); end; end; diff --git a/UConfig.pas b/UConfig.pas index f6bd6d8..7001216 100644 --- a/UConfig.pas +++ b/UConfig.pas @@ -73,13 +73,6 @@ const SMOOTH_SCROLL_STEPS = 5; SMOOTH_SCROLL_STEPS_PAGE = 10; SMOOTH_SCROLL_DURATION_PAGE = 120; -const tuxcmd_rc_file = 'style "treeview-style" {'#10 + - ' GtkTreeView::horizontal_separator = 0'#10 + - ' GtkTreeView::vertical_separator = 0'#10 + - '}'#10 + - 'class "GtkTreeView" style "treeview-style"'; - - var ConfPanelSep, ConfRowHeight, ConfRowHeightReal, ConfNumHistoryItems, ConfMainWindowWidth, ConfMainWindowHeight, ConfMainWindowPosLeft, ConfMainWindowPosTop, ConfMainWindowState, ConfMainWindowLeftSortColumn, ConfMainWindowLeftSortType, ConfMainWindowRightSortColumn, ConfMainWindowRightSortType, @@ -175,34 +175,25 @@ var DataList: TList; ListItem : TGTKListItem; Ext, s, s2 : string; SortOrder: TGTKTreeViewSortOrder; - Time1, Time2: TDateTime; IsRoot: boolean; UsrManager: TUserManager; begin Result := False; - try +// try UsrManager := nil; if LeftPanel then DataList := LeftPanelData else DataList := RightPanelData; IsRoot := (Engine.Path = '/') and (not ((Engine is TVFSEngine) and (Engine as TVFSEngine).ArchiveMode)); -{ Time1 := Now; - Time2 := Now; - DebugMsg(['Get Listing: ', SecondOf(Time2 - Time1), ':', MillisecondOf(Time2 - Time1)]); } - Time1 := Now; SortColumnID := ListView.SortColumnID; SortOrder := ListView.SortOrder; ListView.SetSortInfo(-1, soAscending); ClearListData(DataList); if List.Count + Ord(not IsRoot) < ListView.Items.Count then for i := ListView.Items.Count - 1 downto List.Count + Ord(not IsRoot) do - ListView.Items.Delete(i); + ListView.Items.Delete(i); ItemCount := ListView.Items.Count; - Time2 := Now; - DebugMsg(['Items clear: ', SecondOf(Time2 - Time1), ':', MillisecondOf(Time2 - Time1)]); - - Time1 := Now; if ((Engine is TVFSEngine) and (Engine as TVFSEngine).ArchiveMode) or (Engine.Path <> '/') then AddUpDirItem(ListView, DataList); if List.Count > 0 then @@ -276,25 +267,20 @@ begin DataList.Add(List[i]); ListItem.Data := DataList[DataList.Count - 1]; end; - Time2 := Now; - DebugMsg(['Fill panel: ', SecondOf(Time2 - Time1), ':', MillisecondOf(Time2 - Time1)]); // DebugWriteList(DataList); if Assigned(UsrManager) then UsrManager.Free; - Time1 := Now; ListView.SetSortInfo(SortColumnID, SortOrder); - Time2 := Now; - DebugMsg(['Sorting: ', SecondOf(Time2 - Time1), ':', MillisecondOf(Time2 - Time1)]); DebugMsg(['------------------------------']); Result := True; - except +{ except on E: Exception do begin Application.MessageBox(Format(LANGErrorGettingListingForSPanelNoPath, [LANGPanelStrings[LeftPanel], E.Message]), [mbOK], mbError, mbNone, mbOK); Exit; end; end; -end; +}end; (********************************************************************************************************************************) procedure FindNextSelected(ListView: TGTKListView; DataList: TList; var Item1, Item2: string); diff --git a/UCoreClasses.pas b/UCoreClasses.pas index 7a4a43a..a2b3989 100644 --- a/UCoreClasses.pas +++ b/UCoreClasses.pas @@ -100,7 +100,6 @@ begin Group.GroupName := String(StrToUTF8(grp^.gr_name)); Group.GID := grp^.gr_gid; Group.Users := TStringList.Create; - {$R-} if grp^.gr_mem^ <> nil then begin i := 0; repeat @@ -108,7 +107,6 @@ begin Inc(i); until PCharArray(grp^.gr_mem^)[i] = nil; end; - {$R+} GroupList.Add(Group); grp := getgrent; end; diff --git a/UCoreUtils.pas b/UCoreUtils.pas index a5019d8..8949ed6 100644 --- a/UCoreUtils.pas +++ b/UCoreUtils.pas @@ -133,13 +133,12 @@ var ChildExitStatus: sig_atomic_t; AppPath, IconPath: string; // Used in UFileTypeSettings NormalItemGDKColor, ActiveItemGDKColor, InactiveItemGDKColor, SelectedItemGDKColor, DotFileItemGDKColor, LinkItemGDKColor, - NormalItemGDKBackground, ActiveItemGDKBackground, InactiveItemGDKBackground: PGdkColor; - InactiveItemBGColorNum: Cardinal; + NormalItemGDKBackground, ActiveItemGDKBackground, InactiveItemGDKBackground: PGdkRGBA; implementation -uses DateUtils, GTKForms, GTKUtils, GTKView, ULocale, UConfig, UCore, UGnome, UMain, UFileAssoc; +uses DateUtils, GTKForms, GTKStdCtrls, GTKUtils, GTKView, ULocale, UConfig, UCore, UGnome, UMain, UFileAssoc; (********************************************************************************************************************************) function FormatFloat64(Value: Int64; Sep: string): string; @@ -562,7 +561,6 @@ begin { no '*' in the rest, compare the ends } if HelpWilds = '' then Exit; { '*' is the last letter } { check the rest for equal Length and no '?' } - {$R-} for I := 0 to LenHelpWilds - 1 do begin if (HelpWilds[LenHelpWilds - I] <> InputStr[MaxInputWord - I]) and (HelpWilds[LenHelpWilds - I]<> '?') then @@ -571,7 +569,6 @@ begin Exit; end; end; - {$R+} Exit; end; { handle all to the next '*' } @@ -831,7 +828,7 @@ begin gtk_about_dialog_set_logo(PGtkAboutDialog(about_dialog), AppIcon128.FPixbuf); gtk_window_set_transient_for(PGtkWindow(about_dialog), PGtkWindow(FMain.FWidget)); gtk_dialog_run(PGtkDialog(about_dialog)); - g_object_unref(PGObject(about_dialog)); + gtk_widget_destroy(about_dialog); end; procedure SetupAppIcon; @@ -1170,13 +1167,9 @@ begin memset(args_list, 0, (Length(Parameters) + 1) * sizeof(PChar)); for I := 0 to Length(Parameters) - 1 do begin - {$R-} PCharArray(args_list^)[I] := strdup(PChar(Parameters[i])); - {$R+} end; - {$R-} PCharArray(args_list^)[Length(Parameters)] := nil; - {$R+} end; // Duplicate this process @@ -1418,16 +1411,12 @@ begin for I := 0 to Length(Parameters) - 1 do begin Temp := Parameters[i]; - {$R-} // PCharArray(args_list^)[I] := malloc(Length(Temp)+1); // memset(PCharArray(args_list^)[I], 0, Length(Temp)+1); // StrCopy(PCharArray(args_list^)[I], PChar(Temp)); PCharArray(args_list^)[I] := strdup(PChar(Temp)); - {$R+} end; - {$R-} PCharArray(args_list^)[Length(Parameters)] := nil; - {$R+} end; except on E: Exception do DebugMsg(['*** forked ** function HandleSystemCommand(''', Command, '''):Exception: ', E.Message]); @@ -1720,54 +1709,41 @@ begin end; procedure SetupColors; -var Color: TGDKColor; - LocalListView: TGTKListView; begin - // TODO -{ - LocalListView := TGTKListView.Create(Application); - try - if ConfNormalItemDefaultColors then begin - NormalItemGDKColor := GetDefaultTextColor(LocalListView, GTK_STATE_NORMAL); - NormalItemGDKBackground := GetDefaultBaseColor(LocalListView, GTK_STATE_NORMAL); - end else begin - StringToGDKColor(ConfNormalItemFGColor, Color); - NormalItemGDKColor := GDKColorToPGdkColor(Color); - StringToGDKColor(ConfNormalItemBGColor, Color); - NormalItemGDKBackground := GDKColorToPGdkColor(Color); - end; - if ConfCursorDefaultColors then begin - ActiveItemGDKColor := GetDefaultTextColor(LocalListView, GTK_STATE_SELECTED); - ActiveItemGDKBackground := GetDefaultBaseColor(LocalListView, GTK_STATE_SELECTED); - end else begin - StringToGDKColor(ConfActiveItemFGColor, Color); - ActiveItemGDKColor := GDKColorToPGdkColor(Color); - StringToGDKColor(ConfActiveItemBGColor, Color); - ActiveItemGDKBackground := GDKColorToPGdkColor(Color); - end; - if ConfInactiveItemDefaultColors then begin - InactiveItemGDKColor := GetDefaultTextColor(LocalListView, GTK_STATE_ACTIVE); - InactiveItemGDKBackground := GetDefaultBaseColor(LocalListView, GTK_STATE_ACTIVE); - end else begin - StringToGDKColor(ConfInactiveItemFGColor, Color); - InactiveItemGDKColor := GDKColorToPGdkColor(Color); - StringToGDKColor(ConfInactiveItemBGColor, Color); - InactiveItemGDKBackground := GDKColorToPGdkColor(Color); - end; - StringToGDKColor(ConfSelectedItemFGColor, Color); - SelectedItemGDKColor := GDKColorToPGdkColor(Color); - StringToGDKColor(ConfDotFileItemFGColor, Color); - DotFileItemGDKColor := GDKColorToPGdkColor(Color); - StringToGDKColor(ConfLinkItemFGColor, Color); - LinkItemGDKColor := GDKColorToPGdkColor(Color); - try - InactiveItemBGColorNum := $FF + (InactiveItemGDKBackground^.red div 256) shl 24 - + (InactiveItemGDKBackground^.green div 256) shl 16 - + (InactiveItemGDKBackground^.blue div 256) shl 8; - except InactiveItemBGColorNum := $D0D0D0FF; end; - finally - LocalListView.Free; - end;} + if Assigned(NormalItemGDKColor) then gdk_rgba_free(NormalItemGDKColor); + if Assigned(ActiveItemGDKColor) then gdk_rgba_free(ActiveItemGDKColor); + if Assigned(InactiveItemGDKColor) then gdk_rgba_free(InactiveItemGDKColor); + if Assigned(SelectedItemGDKColor) then gdk_rgba_free(SelectedItemGDKColor); + if Assigned(DotFileItemGDKColor) then gdk_rgba_free(DotFileItemGDKColor); + if Assigned(LinkItemGDKColor) then gdk_rgba_free(LinkItemGDKColor); + if Assigned(NormalItemGDKBackground) then gdk_rgba_free(NormalItemGDKBackground); + if Assigned(ActiveItemGDKBackground) then gdk_rgba_free(ActiveItemGDKBackground); + if Assigned(InactiveItemGDKBackground) then gdk_rgba_free(InactiveItemGDKBackground); + NormalItemGDKColor := nil; + ActiveItemGDKColor := nil; + InactiveItemGDKColor := nil; + SelectedItemGDKColor := nil; + DotFileItemGDKColor := nil; + LinkItemGDKColor := nil; + NormalItemGDKBackground := nil; + ActiveItemGDKBackground := nil; + InactiveItemGDKBackground := nil; + + if not ConfNormalItemDefaultColors then begin + NormalItemGDKColor := StringToGDKRGBA(ConfNormalItemFGColor); + NormalItemGDKBackground := StringToGDKRGBA(ConfNormalItemBGColor); + end; + if not ConfCursorDefaultColors then begin + ActiveItemGDKColor := StringToGDKRGBA(ConfActiveItemFGColor); + ActiveItemGDKBackground := StringToGDKRGBA(ConfActiveItemBGColor); + end; + if not ConfInactiveItemDefaultColors then begin + InactiveItemGDKColor := StringToGDKRGBA(ConfInactiveItemFGColor); + InactiveItemGDKBackground := StringToGDKRGBA(ConfInactiveItemBGColor); + end; + SelectedItemGDKColor := StringToGDKRGBA(ConfSelectedItemFGColor); + DotFileItemGDKColor := StringToGDKRGBA(ConfDotFileItemFGColor); + LinkItemGDKColor := StringToGDKRGBA(ConfLinkItemFGColor); end; (********************************************************************************************************************************) @@ -1849,12 +1825,12 @@ end; function CLAMP(x, MinX, MaxX: integer): integer; begin - if x<MinX then - Result:=MinX - else if x>MaxX then - Result:=MaxX + if x < MinX then + Result := MinX + else if x > MaxX then + Result := MaxX else - Result:=x; + Result := x; end; @@ -1868,9 +1844,15 @@ initialization InternalLockInit(True); SetupSignals; - // Parse tuxcmd rc file - // TODO -// gtk_rc_parse_string(tuxcmd_rc_file); + NormalItemGDKColor := nil; + ActiveItemGDKColor := nil; + InactiveItemGDKColor := nil; + SelectedItemGDKColor := nil; + DotFileItemGDKColor := nil; + LinkItemGDKColor := nil; + NormalItemGDKBackground := nil; + ActiveItemGDKBackground := nil; + InactiveItemGDKBackground := nil; AppPath := IncludeTrailingPathDelimiter(GetHomePath); IconPath := IncludeTrailingPathDelimiter(GetHomePath); diff --git a/UEngines.pas b/UEngines.pas index 2d69695..13acf84 100644 --- a/UEngines.pas +++ b/UEngines.pas @@ -52,7 +52,7 @@ type Selected, IsDotFile, IsExecutable: boolean; atime, mtime, ctime: time_t; Icon: Pointer; - ItemColor: PGdkColor; + ItemColor: PGdkRGBA; end; PDataItemSL = ^TDataItemSL; diff --git a/UFileAssoc.pas b/UFileAssoc.pas index 3e14bf5..0924866 100644 --- a/UFileAssoc.pas +++ b/UFileAssoc.pas @@ -244,8 +244,7 @@ begin end; procedure AssignFileType(Item: PDataItem); -var AColor: TGDKColor; - Plugin: TVFSPlugin; +var Plugin: TVFSPlugin; Assoc: TFileAssoc; begin with PDataItem(Item)^ do begin @@ -274,12 +273,8 @@ begin then Icon := Assoc.LnkPixmap.FPixbuf else Icon := Assoc.Pixmap.FPixbuf; end; - // TODO -{ if ItemColor = nil then begin - if (Assoc.ColorString = '') or (not StringToGDKColor(Assoc.ColorString, AColor)) - then ItemColor := NormalItemGDKColor - else ItemColor := GDKColorToPGdkColor(AColor); - end; } + if ItemColor = nil then + ItemColor := StringToGDKRGBA(Assoc.ColorString); end; end; end; diff --git a/UFileTypeSettings.pas b/UFileTypeSettings.pas index f868715..de89fd1 100644 --- a/UFileTypeSettings.pas +++ b/UFileTypeSettings.pas @@ -97,7 +97,7 @@ var Column: TGTKTreeViewColumn; l: TGTKLabel; begin FUseGnomeIconEntry := Assigned(gnome_icon_entry_new) and Assigned(gnome_icon_entry_get_filename) and Assigned(gnome_icon_entry_set_filename); - SetDefaultSize(450, 620); + SetDefaultSize(470, 700); Caption := LANGEditFileTypesCaption; Buttons := [mbOK, mbCancel]; TitleEventBox := TGTKEventBox.Create(Self); @@ -230,12 +230,12 @@ begin DescriptionLabel.UseUnderline := True; Grid := TGTKGrid.Create(Self); Grid.RowHomogeneous := False; - Grid.ColHomogeneous := False; + Grid.ColHomogeneous := True; Grid.RowSpacing := 1; Grid.AddControl(0, 0, 1, 1, DescriptionLabel); - Grid.AddControl(1, 0, 3, 1, DescriptionEntry); + Grid.AddControl(1, 0, 4, 1, DescriptionEntry); Grid.AddControl(0, 1, 1, 1, CommandLabel); - Grid.AddControl(1, 1, 3, 1, CommandEntry); + Grid.AddControl(1, 1, 4, 1, CommandEntry); ActionsHBox2.Homogeneous := False; ActionsHBox2.AddControlEx(AutodetectCheckBox, True, True, 5); ActionsHBox2.AddControlEx(RunInTerminalCheckBox, True, True, 5); @@ -431,7 +431,7 @@ begin Item.ActionList.Add(Action) end; end; - IntAssocList.Add(Item); + IntAssocList.Add(Item); end; end; @@ -23,7 +23,7 @@ interface uses StrUtils, SysUtils, Types, Classes, DateUtils, - lazglib2, lazgobject2, lazpango1, lazgdkpixbuf2, lazgdk3, lazgtk3, + lazglib2, lazgobject2, lazgdk3, lazgtk3, GTKForms, GTKControls, GTKMenus, GTKStdCtrls, GTKExtCtrls, GTKView, GTKConsts, GTKUtils, GTKClasses, GTKPixbuf, UEngines, UConfig, UGnome, UVFSCore, UCoreClasses; @@ -1055,13 +1055,12 @@ procedure TFMain.ConstructColumns(ListView: TGTKListView); var i, FirstColumn, LastColumn: integer; HandlerID: gulong; Column: TGTKTreeViewColumn; - FontDesc: PPangoFontDescription; begin ListView.SelectionMode := smBrowse; GetFirstLastPanelColumn(FirstColumn, LastColumn); // Temporarily disable the fixed height mode to be able to add columns the Pascal way - g_object_set(PGObject(ListView.FWidget), 'fixed_height_mode', [0, nil]); + ListView.FixedHeightMode := False; for i := 1 to ConstNumPanelColumns do if ConfColumnVisible[i] then begin @@ -1088,7 +1087,6 @@ begin Column.Resizable := True; Column.Reorderable := True; -// if not ConfUseSystemFont then ListView.Columns[i - 1].SetProperty('font', ConfPanelFont); Column.SetProperty('ypad', 0); Column.SetProperty('yalign', 0.5); Column.Tag := i; @@ -1112,16 +1110,7 @@ begin HandlerID := g_signal_connect_data(PGObject(Column.FColumn), 'notify::width', TGCallback(@ListViewColumnResized), ListView, nil, G_CONNECT_DEFAULT); g_object_set_data(PGObject(Column.FColumn), 'Width_Notify_Handler', Pointer(HandlerID)); end; - - // Set the list font - // TODO -{ - if not ConfUseSystemFont then begin - FontDesc := pango_font_description_from_string(PChar(ConfPanelFont)); - gtk_widget_modify_font(ListView.FWidget, FontDesc); - end else gtk_widget_modify_font(ListView.FWidget, nil); -} - g_object_set(PGObject(ListView.FWidget), 'fixed_height_mode', [1, nil]); + ListView.FixedHeightMode := True; end; procedure TFMain.FormDestroy(Sender: TObject); @@ -1179,7 +1168,7 @@ begin end; *) ApplicationShuttingDown := True; // Avoid emitting config files refresh event - + // Close all active connections if b then begin if (not LeftPanelNotebook.Visible) and (LeftPanelEngine is TVFSEngine) then begin @@ -1224,19 +1213,12 @@ begin // Unset the columns changed signal because it's called on window close LeftListView.OnColumnsChanged := nil; RightListView.OnColumnsChanged := nil; - + ConfMainWindowState := Integer(WindowState); - if ConfMainWindowState <> 0 then begin - ConfMainWindowPosLeft := TGTKControl(Self).Left; - ConfMainWindowPosTop := TGTKControl(Self).Top; - ConfMainWindowWidth := TGTKControl(Self).Width; - ConfMainWindowHeight := TGTKControl(Self).Height; - end else begin - ConfMainWindowPosLeft := Left; - ConfMainWindowPosTop := Top; - ConfMainWindowWidth := Width; - ConfMainWindowHeight := Height; - end; + ConfMainWindowPosLeft := Left; + ConfMainWindowPosTop := Top; + ConfMainWindowWidth := Width; + ConfMainWindowHeight := Height; for i := 0 to LeftListView.Columns.Count - 1 do ConfColumnSizes[LeftListView.Columns[i].Tag] := LeftListView.Columns[i].Width; ConfMainWindowLeftSortColumn := LeftListView.SortColumnID; @@ -1285,10 +1267,10 @@ begin FillPluginMenu; - FileListTipsInstall(PGtkTreeView(LeftListView.FWidget)); +{ FileListTipsInstall(PGtkTreeView(LeftListView.FWidget)); FileListTipsInstall(PGtkTreeView(RightListView.FWidget)); FileListTipsEnable; - +} // Load and restore panel tabs if ConfSavePanelTabs then try TmpList := TStringList.Create; @@ -1810,7 +1792,7 @@ begin ATabList := RightPanelTabs; TabEngines := RightTabEngines; end; - try +// try if (NewPath = '..') and (Engine.ParentEngine <> nil) and (Engine.Path = '/') then begin CloseVFS(LeftPanel, False); Exit; @@ -1833,7 +1815,7 @@ begin // Threading... OpenDirThread := TOpenDirThread.Create; - DebugMsg(['TFMain.ChangingDir: Creating thread...']); +// DebugMsg(['TFMain.ChangingDir: Creating thread...']); DoThread; if Plugin <> nil then begin @@ -1844,29 +1826,32 @@ begin // Silence the error if password dialog has been cancelled if not OpenDirThread.VFSCallbackCancelled then ShowError(Self, LANGCouldntOpenURIArchive, OpenDirThread.VFSOpenError); - DebugMsg(['TFMain.ChangingDir: Freeing thread...']); +// DebugMsg(['TFMain.ChangingDir: Freeing thread...']); OpenDirThread.Free; end else if not OpenDirThread.ChDirResult then begin // Drop the error message if one of the callback dialogs were cancelled if not OpenDirThread.VFSCallbackCancelled then ShowError(Self, 'Error changing directory', OpenDirThread.ChDirError); - DebugMsg(['TFMain.ChangingDir: Freeing thread...']); +// DebugMsg(['TFMain.ChangingDir: Freeing thread...']); OpenDirThread.Free; end else if not OpenDirThread.ListingResult then begin ShowError(Self, Format('Error getting listing for %s panel', [LANGPanelStrings[LeftPanel]]), OpenDirThread.ListingError); - DebugMsg(['TFMain.ChangingDir: Freeing thread...']); +// DebugMsg(['TFMain.ChangingDir: Freeing thread...']); OpenDirThread.Free; end else begin s := OpenDirThread.ASelItem; Engine := OpenDirThread.AEngine; // set current Engine from the thread (might have been modified due to VFS) if LeftPanel then LeftPanelEngine := Engine else RightPanelEngine := Engine; - DebugMsg(['TFMain.ChangingDir: Freeing thread...']); +// DebugMsg(['TFMain.ChangingDir: Freeing thread...']); OpenDirThread.Free; - FillPanel(DirList, ListView, Engine, LeftPanel); // This is time consuming + // Prevent GtkTreeView accessing invalid item memory + ListView.CellDataFunc := nil; + + FillPanel(DirList, ListView, Engine, LeftPanel); DirList.Free; if DataList.Count > 0 then begin if PreserveSelection and (SelectedFiles.Count > 0) and (DataList.Count > 0) then @@ -1882,10 +1867,9 @@ begin // DebugMsg(['TFMain.ChangingDir: Engine.Path = "', Engine.Path, '", NewPath = "', NewPath, '", HiliString1 = "', HiliString1, '", HiliString2 = "', HiliString2, '"']); if (not b) and ((Engine.Path = '/') or (NewPath = '/')) and (HiliString1 = '') and (HiliString2 = '') then Sel := ListView.ConvertFromSorted(0); ListView.Items[Sel].Selected := True; -// Application.ProcessMessages; ListView.Items[Sel].SetCursor(0, False, False, 0.5, 0); -// Application.ProcessMessages; end; + ListView.CellDataFunc := @ListViewCellDataFunc; UpdatePanelInfo; UpdatePanelInfoDown(LeftPanel); UpdatePanelInfoDown(not LeftPanel); @@ -1901,9 +1885,9 @@ begin Application.ProcessMessages; InternalUnLock; FileListTipsEnable; - except +{ except on E: Exception do DebugMsg(['*** Exception raised in TFMain.ChangingDir (', E.ClassName, '): ', E.Message]); - end; + end; } end; procedure TFMain.DoRefresh(LeftPanel, StaySame, AutoFallback: boolean); @@ -2199,8 +2183,9 @@ var i: integer; begin Result := False; // TODO -{ for i := 0 to AListView.Columns.Count - 1 do - if Assigned(AListView.Columns[i].FColumn^.editable_widget) then Result := True; } +{ for i := 0 to AListView.Columns.Count - 1 do begin + if Assigned(AListView.Columns[i].FColumn^.editable_widget) then Result := True; + end; } end; function TFMain.PanelFindEditableWidget(AListView: TGTKListView): PGtkEditable; @@ -2249,23 +2234,27 @@ begin end; (********************************************************************************************************************************) -procedure TFMain.ListViewCellDataFunc(Sender: TObject; tree_view: PGtkTreeView; tree_column : PGtkTreeViewColumn; cell : PGtkCellRenderer; tree_model : PGtkTreeModel; iter : PGtkTreeIter); + +function GTK_IS_CELL_RENDERER_PIXBUF(obj: pointer) : boolean; +begin + Result := g_type_check_instance_is_a(obj, gtk_cell_renderer_pixbuf_get_type()); +end; + + +procedure TFMain.ListViewCellDataFunc(Sender: TObject; tree_view: PGtkTreeView; tree_column: PGtkTreeViewColumn; cell: PGtkCellRenderer; tree_model: PGtkTreeModel; iter: PGtkTreeIter); var s: PChar; Sel, ImageCol: boolean; Data: PDataItem; i, ColumnID, ColumnIdx: integer; DataList: TList; TreePath: PGtkTreePath; - AFGColor, ABGColor: string; - ABGColorRGBA: TGdkRGBA; -{ Rect, VisibleRect: TGdkRectangle; } + AFGColor: PGdkRGBA; begin + Data := nil; + ImageCol := False; ColumnIdx := gtk_tree_view_column_get_sort_column_id(tree_column); ColumnID := ColumnSortIDs[ColumnIdx + 1] - 1; - ImageCol := False; - // TODO - if ColumnIdx = 0 then ImageCol := Assigned(cell); - Data := nil; + if ColumnIdx = 0 then ImageCol := Assigned(cell) and GTK_IS_CELL_RENDERER_PIXBUF(cell); if Sender = LeftListView then DataList := LeftPanelData else DataList := RightPanelData; TreePath := gtk_tree_model_get_path(tree_model, iter); @@ -2273,18 +2262,12 @@ begin (Sender as TGTKListView).ConvertPathToChild(TreePath); Data := DataList[gtk_tree_path_get_indices(TreePath)^]; gtk_tree_path_free(TreePath); -(* gtk_tree_view_get_cell_area(tree_view, TreePath, nil, @Rect); - gtk_tree_view_get_visible_rect(tree_view, @VisibleRect); - if (Rect.height = 0) or (Rect.height <> ConfRowHeight) or (Rect.y = 0) or (Rect.y > VisibleRect.y + VisibleRect.height) then Exit; *) - -// DebugMsg(['Rendering text ', Data^.ColumnData[ColumnID]]); - if not Assigned(Data) then Exit; + Sel := gtk_tree_selection_iter_is_selected((Sender as TGTKView).FSelection, iter); with Data^ do begin // ################ Prepare colors - // TODO -{ + AFGColor := nil; if Selected then AFGColor := SelectedItemGDKColor else begin if Sel then begin if (Sender as TGTKView).Focused @@ -2292,31 +2275,22 @@ begin else AFGColor := InactiveItemGDKColor; end else AFGColor := ItemColor; end; - if not Sel then ABGColor := NormalItemGDKBackground else - if (Sender as TGTKView).Focused then ABGColor := ActiveItemGDKBackground - else ABGColor := InactiveItemGDKBackground; - // TODO - FG - gdk_rgba_parse(@ABGColorRGBA, PChar(ABGColor)); -} // ################ Setting the properties if not ImageCol then begin if Editing and (InplaceEditItem.Data = Data) and (ColumnID < 3) and ((ColumnID = 0) or (ColumnID = 1) { TODO or Assigned(tree_column^.editable_widget)}) then begin if (ColumnID = 0) or (ColumnID = 1) then s := FDisplayName else s := nil; - // TODO - g_object_set(PGObject(cell), 'text', [s, 'foreground-gdk', PChar(AFGColor), nil]); - g_object_set(PGObject(cell), 'cell-background-rgba', [@ABGColorRGBA, nil]); + g_object_set(PGObject(cell), 'text', ['foreground-rgba', AFGColor, nil]); end else begin // not editing if ConfDirsInBold then begin - if IsDir or UpDir then g_object_set(PGObject(cell), 'markup', [PChar(Format('<span weight="bold">%s</span>', [QuoteMarkupStr(ColumnData[ColumnID])])), 'foreground-gdk', PChar(AFGColor), nil]) - else g_object_set(PGObject(cell), 'markup', [PChar(QuoteMarkupStr(ColumnData[ColumnID])), 'foreground-gdk', PChar(AFGColor), nil]); - end else g_object_set(PGObject(cell), 'text', [ColumnData[ColumnID], 'foreground-gdk', PChar(AFGColor), nil]); - g_object_set(PGObject(cell), 'cell-background-rgba', [@ABGColorRGBA, nil]); + if IsDir or UpDir then g_object_set(PGObject(cell), 'markup', [PChar(Format('<span weight="bold">%s</span>', [QuoteMarkupStr(ColumnData[ColumnID])])), nil]) + else g_object_set(PGObject(cell), 'markup', [PChar(QuoteMarkupStr(ColumnData[ColumnID])), nil]); + end else g_object_set(PGObject(cell), 'text', [ColumnData[ColumnID], nil]); + g_object_set(PGObject(cell), 'foreground-rgba', [AFGColor, nil]); end; - end else // this is the image column + end else // this is an image column if ConfUseFileTypeIcons then begin // Assign icons - g_object_set(PGObject(cell), 'cell-background-rgba', [@ABGColorRGBA, nil]); if Sel and (not (Sender as TGTKView).Focused) then begin if Sender = LeftListView then RedrawLeftInactive := True else RedrawRightInactive := True; @@ -2855,6 +2829,7 @@ var AListView: TGTKListView; i: integer; s1, s2: string; begin + Exit; try InternalLock; AListView := (((Sender as TGTKTreeViewColumn).Parent as TGTKTreeViewColumns).Parent as TGTKListView); @@ -3107,9 +3082,8 @@ begin b := False; for i := 0 to DataList.Count - 1 do with PDataItem(DataList[i])^ do - if (not UpDir) and (not IsDir) and Selected then {$B+} + if (not UpDir) and (not IsDir) and Selected then b := b or FChecksum.ProcessFile(IncludeTrailingPathDelimiter(Engine.Path) + string(FName)); - {$B-} end; if b { and (FChecksum.List.Count > 0) } then FChecksum.Run; finally @@ -4354,6 +4328,7 @@ end; procedure TFMain.ApplySettings(RebuildListViews, RebuildIcons, AStartup: boolean); var i: integer; + CSS: string; begin ButtonsBox.Visible := ConfShowFuncButtons; ButtonBoxSeparator.Visible := ConfShowFuncButtons; @@ -4378,22 +4353,46 @@ begin // Colors Section SetupColors; - // TODO -{ - gtk_widget_modify_base(LeftListView.FWidget, GTK_STATE_NORMAL, NormalItemGDKBackground); - gtk_widget_modify_base(RightListView.FWidget, GTK_STATE_NORMAL, NormalItemGDKBackground); - gtk_widget_modify_base(LeftListView.FWidget, GTK_STATE_SELECTED, ActiveItemGDKBackground); - gtk_widget_modify_base(RightListView.FWidget, GTK_STATE_SELECTED, ActiveItemGDKBackground); - gtk_widget_modify_base(LeftListView.FWidget, GTK_STATE_ACTIVE, InactiveItemGDKBackground); - gtk_widget_modify_base(RightListView.FWidget, GTK_STATE_ACTIVE, InactiveItemGDKBackground); - - gtk_widget_modify_text(LeftListView.FWidget, GTK_STATE_NORMAL, NormalItemGDKColor); - gtk_widget_modify_text(RightListView.FWidget, GTK_STATE_NORMAL, NormalItemGDKColor); - gtk_widget_modify_text(LeftListView.FWidget, GTK_STATE_SELECTED, ActiveItemGDKColor); - gtk_widget_modify_text(RightListView.FWidget, GTK_STATE_SELECTED, ActiveItemGDKColor); - gtk_widget_modify_text(LeftListView.FWidget, GTK_STATE_ACTIVE, InactiveItemGDKColor); - gtk_widget_modify_text(RightListView.FWidget, GTK_STATE_ACTIVE, InactiveItemGDKColor); -} + + CSS := ''; +// CSS := CSS + '* { all: unset; -gtk-outline-radius: 0px; outline-color: transparent; outline-style: none; outline-offset: 0px; outline-width: 0px; }'#10; + CSS := CSS + 'treeview.view:nth-child(2) {'#10; + CSS := CSS + ' -gtk-outline-radius: 0px;'#10' outline-color: transparent;'#10' outline-style: none;'#10' outline-offset: 0px;'#10' outline-width: 0px;'#10; + if not ConfUseSystemFont then CSS := CSS + ' ' + PangoFontDescToCSS(ConfPanelFont) + #10; + if Assigned(NormalItemGDKBackground) then CSS := CSS + ' background-color: ' + GDKRGBAToString(NormalItemGDKBackground) + ';'#10; + if Assigned(NormalItemGDKColor) then CSS := CSS + ' color: ' + GDKRGBAToString(NormalItemGDKColor) + ';'#10; +// CSS := CSS + ' -GtkTreeView-vertical-separator: 10px;'#10' -GtkTreeView-horizontal-separator: 10px;'#10; + + CSS := CSS + '}'#10; + +(* CSS := CSS + 'row, .row, .cell, treeview.cell, treeview.row, treeview cell, treeview row {'#10 + + ' border-width: 0px; border-radius: 0px; border-image: none; border: none;'#10 + + ' background-color:yellow; background-image: none;'#10 + + ' padding: 0px; margin: 0px; box-shadow: none; '#10 + + ' outline-style: none; outline-offset: 0px; outline-width: 0px; outline-color: yellow;'#10 + + '}'#10; +*) + + if Assigned(ActiveItemGDKBackground) or Assigned(ActiveItemGDKColor) then begin + CSS := CSS + 'treeview.cell:selected:focus {'#10; + if Assigned(ActiveItemGDKColor) then CSS := CSS + ' color: ' + GDKRGBAToString(ActiveItemGDKColor) + ';'#10; + if Assigned(ActiveItemGDKBackground) then CSS := CSS + ' background-color: ' + GDKRGBAToString(ActiveItemGDKBackground) + ';'#10 + + ' background-image: image(' + GDKRGBAToString(ActiveItemGDKBackground) + ');'#10 + + ' border-style: none; border-width: 0;'#10; + CSS := CSS + '}'#10; + end; + if Assigned(InactiveItemGDKBackground) or Assigned(InactiveItemGDKColor) then begin + CSS := CSS + 'treeview.cell:selected {'#10; + if Assigned(InactiveItemGDKColor) then CSS := CSS + ' color: ' + GDKRGBAToString(InactiveItemGDKColor) + ';'#10; + if Assigned(InactiveItemGDKBackground) then CSS := CSS + ' background-color: ' + GDKRGBAToString(InactiveItemGDKBackground) + ';'#10 + + ' background-image: image(' + GDKRGBAToString(InactiveItemGDKBackground) + ');'#10 + + ' border-style: none; border-width: 0;'#10; + CSS := CSS + '}'#10; + end; + writeln(css); + LeftListView.ApplyCustomCSS(CSS); + RightListView.ApplyCustomCSS(CSS); + // Resize commandline history if ConfNumHistoryItems < CommandLineHistory.Count then begin try @@ -4798,11 +4797,10 @@ procedure TFMain.FillMounterBar; 3 : Pixmap := MounterFloppy; 4 : Pixmap := MounterNetwork; end; - // TODO if ConfMounterPushDown then begin -// (Button as TGTKToggleButton).Icon := Pixmap; + (Button as TGTKToggleButton).Icon := Pixmap; (Button as TGTKToggleButton).Checked := Mounted; - end; // TODO else Button.Icon := Pixmap; + end else Button.Icon := Pixmap; Button.OnClick := @MounterButtonClick; // It has to be here because setting the Checked property causes the signal emitting Button.MarginTop := 1; @@ -5004,7 +5002,6 @@ begin try InternalLock; FColumns := TFColumns.Create(Self); -// FColumns.Show; if FColumns.Run = mbOK then begin FColumns.ApplyColumnList; RebuildListViews(True); @@ -5151,19 +5148,19 @@ begin end; procedure TFMain.miPluginAboutClick(Sender: TObject); -const Authors : array[0..1] of PChar = ('', nil); -var AboutBox: PGtkWidget; - VFSItem: TVFSPlugin; +var VFSItem: TVFSPlugin; + about_dialog: PGtkWidget; begin + InternalLock; VFSItem := TVFSPlugin(PluginList[(Sender as TGTKMenuItem).Tag]); - InternalLock; - // TODO - Application.MessageBox(Format(LANGPluginAboutInside, [VFSItem.ModuleName, VFSItem.ModuleAbout, VFSItem.ModuleCopyright])); -{ else begin - AboutBox := gnome_about_new(PChar(VFSItem.ModuleName), nil, PChar(VFSItem.ModuleCopyright), PChar(VFSItem.ModuleAbout), @Authors, nil, nil, AppIcon64.FPixbuf); - gtk_window_set_transient_for(PGtkWindow(AboutBox), PGtkWindow(FMain.FWidget)); - gtk_dialog_run(PGtkDialog(AboutBox)); - end; } + about_dialog := gtk_about_dialog_new(); + gtk_about_dialog_set_program_name(PGtkAboutDialog(about_dialog), PChar(VFSItem.ModuleName)); + gtk_about_dialog_set_version(PGtkAboutDialog(about_dialog), PChar(VFSItem.ModuleAbout)); + gtk_about_dialog_set_copyright(PGtkAboutDialog(about_dialog), PChar(VFSItem.ModuleCopyright)); + gtk_about_dialog_set_logo(PGtkAboutDialog(about_dialog), AppIcon64.FPixbuf); + gtk_window_set_transient_for(PGtkWindow(about_dialog), PGtkWindow(FMain.FWidget)); + gtk_dialog_run(PGtkDialog(about_dialog)); + gtk_widget_destroy(about_dialog); InternalLockInit(False); end; diff --git a/UPreferences.pas b/UPreferences.pas index f66c1eb..81eecdb 100644 --- a/UPreferences.pas +++ b/UPreferences.pas @@ -1094,24 +1094,14 @@ end; procedure TFPreferences.ColorButtonDefaultsToggled(Sender: TObject); begin -{ - if NormalItemFGColorDefault.Checked then NormalItemFGColorButton.SetDefaultColor - else NormalItemFGColorButton.UnsetDefaultColor; - if NormalItemFGColorDefault.Checked then NormalItemBGColorButton.SetDefaultColor - else NormalItemBGColorButton.UnsetDefaultColor; - if ActiveItemFGColorDefault.Checked then ActiveItemFGColorButton.SetDefaultColor - else ActiveItemFGColorButton.UnsetDefaultColor; - if ActiveItemFGColorDefault.Checked then ActiveItemBGColorButton.SetDefaultColor - else ActiveItemBGColorButton.UnsetDefaultColor; - if InactiveItemFGColorDefault.Checked then InactiveItemFGColorButton.SetDefaultColor - else InactiveItemFGColorButton.UnsetDefaultColor; - if InactiveItemFGColorDefault.Checked then InactiveItemBGColorButton.SetDefaultColor - else InactiveItemBGColorButton.UnsetDefaultColor; - if LinkItemFGColorDefault.Checked then LinkItemFGColorButton.SetDefaultColor - else LinkItemFGColorButton.UnsetDefaultColor; - if DotFileItemFGColorDefault.Checked then DotFileItemFGColorButton.SetDefaultColor - else DotFileItemFGColorButton.UnsetDefaultColor; -} + NormalItemFGColorButton.Enabled := not NormalItemFGColorDefault.Checked; + NormalItemBGColorButton.Enabled := not NormalItemFGColorDefault.Checked; + ActiveItemFGColorButton.Enabled := not ActiveItemFGColorDefault.Checked; + ActiveItemBGColorButton.Enabled := not ActiveItemFGColorDefault.Checked; + InactiveItemFGColorButton.Enabled := not InactiveItemFGColorDefault.Checked; + InactiveItemBGColorButton.Enabled := not InactiveItemFGColorDefault.Checked; + LinkItemFGColorButton.Enabled := not LinkItemFGColorDefault.Checked; + DotFileItemFGColorButton.Enabled := not DotFileItemFGColorDefault.Checked; end; procedure TFPreferences.DefaultRowHeightCheckBoxToggled(Sender: TObject); diff --git a/libgtk_kylix/GTKControls.pas b/libgtk_kylix/GTKControls.pas index 4729266..502e1b9 100644 --- a/libgtk_kylix/GTKControls.pas +++ b/libgtk_kylix/GTKControls.pas @@ -82,6 +82,7 @@ type FOnDblClick: TGDKMouseEvent; FOnExpose: TGDKExposeEvent; FOnMouseMove: TGDKMouseEvent; + FCSSProvider: PGtkCssProvider; function GetWidth: Integer; function GetHeight: Integer; function GetLeft: Integer; @@ -141,6 +142,7 @@ type procedure Invalidate; function GetData(Key: string): Pointer; procedure SetData(Key: string; Value: Pointer); + procedure ApplyCustomCSS(Stylesheet: string); published property Width: Integer read GetWidth write SetWidth; property Height: Integer read GetHeight write SetHeight; @@ -301,14 +303,16 @@ begin FOnMouseMove := nil; FOnMouseDown := nil; FOnMouseUp := nil; + FCSSProvider := nil; end; destructor TGTKControl.Destroy; begin - try + if Assigned(FCSSProvider) then g_object_unref(PGObject(FCSSProvider)); +// try // SetParent(nil); // if Assigned(FWidget) {and GTK_IS_WIDGET(FWidget)} then gtk_widget_destroy(PGtkWidget(FWidget)); - except end; +// except end; inherited Destroy; end; @@ -381,6 +385,7 @@ end; function TGTKControl.GetLeft: Integer; var A: TGtkAllocation; begin + A.x := 0; gtk_widget_get_allocation(FWidget, @A); Result := A.x; end; @@ -388,6 +393,7 @@ end; function TGTKControl.GetTop: Integer; var A: TGtkAllocation; begin + A.y := 0; gtk_widget_get_allocation(FWidget, @A); Result := A.y; end; @@ -776,6 +782,32 @@ begin gtk_widget_set_margin_bottom(FWidget, Value); end; +procedure TGTKControl.ApplyCustomCSS(Stylesheet: string); +var provider: PGtkCssProvider; + error: PGError; +begin + error := nil; + // No stylesheet previously attached and asked to reset, nothing to do + if not Assigned(FCSSProvider) and (Length(Stylesheet) < 1) then Exit; + // Create new stylesheet provider + if not Assigned(FCSSProvider) then begin + FCSSProvider := gtk_css_provider_new(); + gtk_style_context_add_provider(gtk_widget_get_style_context(FWidget), PGtkStyleProvider(FCSSProvider), G_MAXUINT32); + end; + // Asked to clear the stylesheets + if Length(Stylesheet) < 1 then begin + gtk_style_context_remove_provider(gtk_widget_get_style_context(FWidget), PGtkStyleProvider(FCSSProvider)); + g_object_unref(PGObject(FCSSProvider)); + FCSSProvider := nil; + end else begin + // Apply the stylesheet + if not gtk_css_provider_load_from_data(FCSSProvider, PChar(Stylesheet), -1, @Error) then begin + g_log(PChar('tuxcmd'), [G_LOG_LEVEL_WARNING], 'Failed to parse CSS stylesheet "%s": %s', [PChar(Stylesheet), Error^.message]); + g_error_free(error); + Exit; + end; + end; +end; (********************************************************************************************************************************) (********************************************************************************************************************************) @@ -812,7 +844,7 @@ end; function TGTKContainer.GetChildrenCount: integer; var List: PGList; begin - List := LAZGLIB2.PGList(gtk_container_get_children(PGtkContainer(FWidget))); + List := gtk_container_get_children(PGtkContainer(FWidget)); Result := g_list_length(List); g_list_free(List); end; diff --git a/libgtk_kylix/GTKDialogs.pas b/libgtk_kylix/GTKDialogs.pas index dfbe1b2..ff8a0b0 100644 --- a/libgtk_kylix/GTKDialogs.pas +++ b/libgtk_kylix/GTKDialogs.pas @@ -135,7 +135,7 @@ end; function TGTKColorButton.GetColor: string; var c: TGdkRGBA; begin - FillChar(c, sizeof(TGdkRGBA), 0); + Initialize(c); gtk_color_chooser_get_rgba(PGtkColorChooser(FWidget), @c); Result := string(gdk_rgba_to_string(@c)); end; @@ -149,7 +149,8 @@ end; procedure TGTKColorButton.SetDefaultColor; begin - gtk_color_chooser_set_rgba(PGtkColorChooser(FWidget), nil); + // No way to reset the widget to an empty state, just set grey + SetColor('#EEEEEE'); end; (********************************************************************************************************************************) diff --git a/libgtk_kylix/GTKForms.pas b/libgtk_kylix/GTKForms.pas index b1467db..0dc1691 100644 --- a/libgtk_kylix/GTKForms.pas +++ b/libgtk_kylix/GTKForms.pas @@ -70,6 +70,9 @@ type // Some basic types FOnShow: TNotifyEvent; FCaption: string; FOnDestroy: TNotifyEvent; + FDeleteEventSignalHandlerID: gulong; + FSizeAllocateSignalHandlerID: gulong; + FShowSignalHandlerID: gulong; function GetWindowPosition: TWindowPosition; function GetResizeable: boolean; function GetWindowTypeHint: TGDKWindowTypeHint; @@ -88,6 +91,7 @@ type // Some basic types procedure SetWidth(Value: integer); procedure SetHeight(Value: integer); procedure SetDefault(Value: TGTKControl); + procedure ConnectDefaultSignals; protected procedure DoClose(var Action: TCloseAction); dynamic; property Visible write SetVisible default False; @@ -182,7 +186,7 @@ type // Some basic types destructor Destroy; override; procedure ControlDestroyed(Control: TGTKControl); procedure CreateForm(InstanceClass: TComponentClass; var Reference); - procedure HandleException(Sender: TObject); +// procedure HandleException(Sender: TObject); procedure HandleMessage; procedure HookSynchronizeWakeup; procedure Initialize; @@ -192,7 +196,7 @@ type // Some basic types Default: TMessageButton = mbNone; Escape: TMessageButton = mbNone): TMessageButton; overload; procedure ProcessMessages; procedure Run; - procedure ShowException(E: Exception); +// procedure ShowException(E: Exception); procedure Terminate; procedure UnhookSynchronizeWakeup; property MainForm: TCustomGTKForm read FMainForm; @@ -207,8 +211,6 @@ type // Some basic types var Application: TGTKApplication; Screen: TGDKScreen; - Argc: Integer; - Argv: PPChar; function GetParentForm(Control: TGTKControl): TCustomGTKForm; @@ -286,6 +288,9 @@ begin FOnClose := nil; FOnCloseQuery := nil; FOnDestroy := nil; + FDeleteEventSignalHandlerID := 0; + FSizeAllocateSignalHandlerID := 0; + FShowSignalHandlerID := 0; FCaption := ''; FAccelGroup := gtk_accel_group_new; Screen.AddForm(Self); @@ -293,15 +298,22 @@ end; destructor TCustomGTKForm.Destroy; begin - try - Screen.RemoveForm(Self); - if Assigned(FOnDestroy) then FOnDestroy(Self); - except - end; + Screen.RemoveForm(Self); + if Assigned(FOnDestroy) then FOnDestroy(Self); +// if FDeleteEventSignalHandlerID > 0 then g_signal_handler_disconnect(PGObject(FWidget), FDeleteEventSignalHandlerID); +// if FSizeAllocateSignalHandlerID > 0 then g_signal_handler_disconnect(PGObject(FWidget), FSizeAllocateSignalHandlerID); +// if FShowSignalHandlerID > 0 then g_signal_handler_disconnect(PGObject(FWidget), FShowSignalHandlerID); if not Application.Terminated then gtk_widget_destroy(FWidget); inherited Destroy; end; +procedure TCustomGTKForm.ConnectDefaultSignals; +begin + FDeleteEventSignalHandlerID := g_signal_connect_data(PGObject(FWidget), 'delete-event', TGCallback(@TCustomGTKForm_delete_event), Self, nil, G_CONNECT_DEFAULT); + FSizeAllocateSignalHandlerID := g_signal_connect_data(PGObject(FWidget), 'size-allocate', TGCallback(@TCustomGTKForm_size_allocate), Self, nil, G_CONNECT_DEFAULT); + FShowSignalHandlerID := g_signal_connect_data(PGObject(FWidget), 'show', TGCallback(@TCustomGTKForm_show), Self, nil, G_CONNECT_DEFAULT); +end; + procedure TCustomGTKForm.SetVisible(Value: Boolean); begin inherited Visible := Value; @@ -339,7 +351,7 @@ end; procedure TCustomGTKForm.Release; begin -// SetParent(nil); + SetParent(nil); // if Assigned(FWidget) and GTK_IS_WIDGET(FWidget) then gtk_widget_destroy(PGtkWidget(FWidget)); end; @@ -407,6 +419,7 @@ end; function TCustomGTKForm.GetWindowState: TGDKWindowState; begin + if gtk_window_is_maximized(PGtkWindow(FWidget)) then Result := wsMaximized else Result := TGDKWindowState(gdk_window_get_state(PGdkWindow(FWidget^.window))); end; @@ -514,48 +527,31 @@ begin inherited Create(AOwner); FMainForm := nil; FMainFormSet := False; - if not Assigned(Classes.ApplicationHandleException) then +{ if not Assigned(Classes.ApplicationHandleException) then Classes.ApplicationHandleException := @HandleException; if not Assigned(Classes.ApplicationShowException) then - Classes.ApplicationShowException := @ShowException; + Classes.ApplicationShowException := @ShowException;} CreateHandle; HookSynchronizeWakeup; FThreadID := 0; end; -procedure my_g_thread_init(vtable:Pointer);cdecl;external 'libgthread-2.0.so' name 'g_thread_init'; - procedure TGTKApplication.CreateHandle; -var - I: Integer; - Temp: string; +var argc: gint; + argv: PPgchar; + i: Integer; begin - Argc := ParamCount + 1; - Argv := AllocMem((Argc + 1) * SizeOf(PChar)); - for I := 0 to Argc - 1 do - begin - Temp := ParamStr(I); - {$R-} - PCharArray(Argv^)[I] := AllocMem(Length(Temp)+1); - StrCopy(PCharArray(Argv^)[I], PChar(Temp)); - {$R+} - end; - {$R-} - PCharArray(Argv^)[Argc] := nil; - {$R+} - - // Init threads - my_g_thread_init(nil); - - (* ATTENTION: do not call gdk_threads_init(), it causes deadlocks and we don't really need it *) -// gdk_threads_init; + argc := ParamCount; + argv := g_malloc0(argc * sizeof(Pointer)); + for i := 0 to argc - 1 do + argv[i] := g_strdup(PChar(ParamStr(i))); // Initialize the widget set gtk_init(@argc, @argv); -{ if not gtk_init_check(@argc, @argv) then begin - WriteLn('Unable to initialize GTK+ interface. Make sure you have correctly installed all of GTK libraries and have set a valid X server in the DISPLAY variable.'); - Halt(1); - end; } + + for i := 0 to argc - 1 do + g_free(argv[i]); + g_free(argv); end; destructor TGTKApplication.Destroy; @@ -565,31 +561,34 @@ var P: TNotifyEvent; E: TExceptionEvent; begin - UnhookSynchronizeWakeup; +{ UnhookSynchronizeWakeup; P := @HandleException; if @P = @Classes.ApplicationHandleException then Classes.ApplicationHandleException := nil; E := @ShowException; if @E = @Classes.ApplicationShowException then Classes.ApplicationShowException := nil; +} inherited Destroy; end; procedure TGTKApplication.HookSynchronizeWakeup; begin - if not Assigned(Classes.WakeMainThread) then - Classes.WakeMainThread := WakeMainThread; +{ if not Assigned(Classes.WakeMainThread) then + Classes.WakeMainThread := WakeMainThread; } end; procedure TGTKApplication.UnhookSynchronizeWakeup; var P: TNotifyEvent; begin - P := WakeMainThread; +{ P := WakeMainThread; if @P = @Classes.WakeMainThread then Classes.WakeMainThread := nil; +} end; +{ procedure TGTKApplication.HandleException(Sender: TObject); begin if ExceptObject is Exception then @@ -602,6 +601,7 @@ begin end else SysUtils.ShowException(ExceptObject, ExceptAddr); end; +} procedure TGTKApplication.CreateForm(InstanceClass: TComponentClass; var Reference); var @@ -662,11 +662,13 @@ function __pthread_self: __pthread_t; cdecl; external 'libpthread.so.0' name 'pt procedure TGTKApplication.Run; begin - repeat + gtk_main(); + +{ repeat try // gdk_threads_enter; - FThreadID := __pthread_self; - gtk_main; + FThreadID := __pthread_self(); + gtk_main(); // gdk_threads_leave; except on E : Exception do @@ -677,6 +679,7 @@ begin end else HandleException(E); end; until Terminated; + } end; function TGTKApplication_MessageBox_key_press_event(widget: PGtkWidget; event: PGdkEventKey; user_data : gpointer): gboolean; cdecl; @@ -709,7 +712,7 @@ begin Result := Escape; Exit; end; - Dialog := gtk_message_dialog_new(ParentWindow, [GTK_DIALOG_MODAL, GTK_DIALOG_DESTROY_WITH_PARENT], TMessageStyleID[Integer(Style)], + Dialog := gtk_message_dialog_new_with_markup(ParentWindow, [GTK_DIALOG_MODAL, GTK_DIALOG_DESTROY_WITH_PARENT], TMessageStyleID[Integer(Style)], GTK_BUTTONS_NONE, '%s', [PChar(Text)]); for i := 1 to NumMessageButtons do if TMessageButton(i - 1) in Buttons @@ -721,6 +724,7 @@ begin gtk_widget_destroy(Dialog); end; +{ procedure TGTKApplication.ShowException(E: Exception); var Msg: string; begin @@ -728,6 +732,7 @@ begin if (Msg <> '') and (AnsiLastChar(Msg) = '.') then Delete(Msg, Length(Msg), 1); MessageBox(Format('An unhandled exception has occured: '#10' %s'#10#10'It is strongly recommended to save your data and quit the application.', [Msg]), [mbOk], mbError); end; +} procedure TGTKApplication.Terminate; begin @@ -751,13 +756,11 @@ begin inherited Create(AOwner); FWidget := gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_add_accel_group(PGtkWindow(FWidget), FAccelGroup); - g_signal_connect_data(PGObject(FWidget), 'delete-event', TGCallback(@TCustomGTKForm_delete_event), Self, nil, G_CONNECT_DEFAULT); - g_signal_connect_data(PGObject(FWidget), 'size-allocate', TGCallback(@TCustomGTKForm_size_allocate), Self, nil, G_CONNECT_DEFAULT); - g_signal_connect_data(PGObject(FWidget), 'show', TGCallback(@TCustomGTKForm_show), Self, nil, G_CONNECT_DEFAULT); Visible := False; SetResizeable(True); FormCreate(Self); if Visible then Show; + ConnectDefaultSignals; end; procedure TGTKForm.Hide; @@ -784,9 +787,6 @@ begin if Assigned(AOwner) and (AOwner is TCustomGTKForm) then SetTransientFor(AOwner as TCustomGTKForm); FOnResponse := nil; gtk_window_add_accel_group(PGtkWindow(FWidget), FAccelGroup); - g_signal_connect_data(PGObject(FWidget), 'delete-event', TGCallback(@TCustomGTKForm_delete_event), Self, nil, G_CONNECT_DEFAULT); - g_signal_connect_data(PGObject(FWidget), 'show', TGCallback(@TCustomGTKForm_show), Self, nil, G_CONNECT_DEFAULT); - g_signal_connect_data(PGObject(FWidget), 'response', TGCallback(@TGTKDialog_response_event), Self, nil, G_CONNECT_DEFAULT); ClientArea := TGTKVBox.CreateLinked(Self, gtk_dialog_get_content_area(PGtkDialog(FWidget))); ActionArea := TGTKHBox.CreateLinked(Self, gtk_dialog_get_action_area(PGtkDialog(FWidget))); FButtons := []; @@ -794,6 +794,7 @@ begin SetResizeable(True); FormCreate(Self); if Visible then Show; + ConnectDefaultSignals; end; function TGTKDialog.Run: TMessageButton; diff --git a/libgtk_kylix/GTKStdCtrls.pas b/libgtk_kylix/GTKStdCtrls.pas index 2bca3bb..7f73594 100644 --- a/libgtk_kylix/GTKStdCtrls.pas +++ b/libgtk_kylix/GTKStdCtrls.pas @@ -23,7 +23,7 @@ unit GTKStdCtrls; interface -uses lazglib2, lazgobject2, lazgtk3, Classes, GTKControls, GTKConsts; +uses lazglib2, lazgobject2, lazgtk3, Classes, GTKControls, GTKPixbuf, GTKConsts; type @@ -32,12 +32,14 @@ type TGTKButton = class(TGTKBin) private FOnClick: TNotifyEvent; + FImage: PGtkWidget; function GetCaption: string; function GetUseUnderline: boolean; function GetBorderStyle: TGTKBorderStyle; procedure SetCaption(Value: string); procedure SetUseUnderline(Value: boolean); procedure SetBorderStyle(Value: TGTKBorderStyle); + procedure SetIcon(Value: TGDKPixbuf); public constructor Create(AOwner: TComponent); override; constructor CreateFromIconName(AOwner: TComponent; const IconName: string); @@ -47,6 +49,7 @@ type property OnClick: TNotifyEvent read FOnClick write FOnClick; property UseUnderline: boolean read GetUseUnderline write SetUseUnderline; property BorderStyle: TGTKBorderStyle read GetBorderStyle write SetBorderStyle; + property Icon: TGDKPixbuf write SetIcon; end; (****************************************** TGTKLABEL **************************************************************************) @@ -302,6 +305,20 @@ begin gtk_button_set_relief(PGtkButton(FWidget), TGtkReliefStyle(Value)); end; +procedure TGTKButton.SetIcon(Value: TGDKPixbuf); +begin + if Assigned(Value) then begin + if Assigned(FImage) then g_object_unref(PGObject(FImage)); + FImage := gtk_image_new_from_pixbuf(Value.FPixbuf); + gtk_button_set_image(PGtkButton(FWidget), FImage); + gtk_button_set_always_show_image(PGtkButton(FWidget), True); + end else begin + gtk_button_set_image(PGtkButton(FWidget), nil); + g_object_unref(PGObject(FImage)); + FImage := nil; + end; +end; + (********************************************************************************************************************************) (********************************************************************************************************************************) constructor TGTKLabel.Create(AOwner: TComponent); diff --git a/libgtk_kylix/GTKUtils.pas b/libgtk_kylix/GTKUtils.pas index c1b662e..1b3e7e8 100644 --- a/libgtk_kylix/GTKUtils.pas +++ b/libgtk_kylix/GTKUtils.pas @@ -32,27 +32,35 @@ function AllocateColor(R, G, B: Word): TGDKColor; overload; *) function KeyValToUnicode(const Key: word): guint32; function UnicodeToKeyVal(const UnicodeVal: guint32): word; -(* -function GetDefaultForegroundColor(State: integer): PGdkColor; overload; -function GetDefaultForegroundColor(Widget: TGTKControl; State: integer): PGdkColor; overload; -function GetDefaultBackgroundColor(State: integer): PGdkColor; overload; -function GetDefaultBackgroundColor(Widget: TGTKControl; State: integer): PGdkColor; overload; -function GetDefaultBaseColor(State: integer): PGdkColor; overload; -function GetDefaultBaseColor(Widget: TGTKControl; State: integer): PGdkColor; overload; -function GetDefaultTextColor(State: integer): PGdkColor; overload; -function GetDefaultTextColor(Widget: TGTKControl; State: integer): PGdkColor; overload; +{ +function GetDefaultForegroundColor(State: TGtkStateFlags): PGdkRGBA; overload; +function GetDefaultForegroundColor(Widget: TGTKControl; State: TGtkStateFlags): PGdkRGBA; overload; +} +function GetDefaultBackgroundColor(Widget: TGTKControl; State: TGtkStateFlags): PGdkRGBA; overload; +{ +function GetDefaultBaseColor(State: TGtkStateFlags): PGdkRGBA; overload; +function GetDefaultBaseColor(Widget: TGTKControl; State: TGtkStateFlags): PGdkRGBA; overload; +} +// Returns newly allocated PGdkRGBA +function GetDefaultTextColor(Widget: TGTKControl; State: TGtkStateFlags): PGdkRGBA; +{ function GDKColorToPGdkRGBA(Color: TGDKColor): PGdkRGBA; -function PGdkRGBAToGDKColor(Color: PGdkRGBA): TGDKColor; -function GDKColorToString(Color: TGDKColor): string; -function StringToGDKColor(Str: string; var Color: TGDKColor): boolean; -*) +function PGdkRGBAToGDKColor(Color: PGdkRGBA): TGDKColor;} + +function GDKRGBAToString(Color: PGdkRGBA): string; +function StringToGDKRGBA(Str: string): PGdkRGBA; + function ValidateColorString(const Color: string): boolean; +function PangoFontDescToCSS(const PangoFontDesc: string): string; + (********************************************************************************************************************************) implementation +uses lazpango1; + (********************************************************************************************************************************) (* function AllocateColor(Widget: PGtkWidget; R, G, B: Word): PGdkColor; @@ -89,7 +97,7 @@ end; (********************************************************************************************************************************) (* -function GetDefaultForegroundColor(State: integer): PGdkColor; +function GetDefaultForegroundColor(State: TGtkStateFlags): PGdkRGBA; var Widget: PGtkWidget; Style: PGtkStyle; begin @@ -99,7 +107,7 @@ begin gtk_widget_destroy(Widget); end; -function GetDefaultForegroundColor(Widget: TGTKControl; State: integer): PGdkColor; +function GetDefaultForegroundColor(Widget: TGTKControl; State: TGtkStateFlags): PGdkRGBA; var Style: PGtkStyle; begin Style := gtk_rc_get_style(Widget.FWidget); @@ -108,28 +116,20 @@ end; *) (********************************************************************************************************************************) -(* -function GetDefaultBackgroundColor(State: integer): PGdkColor; -var Widget: PGtkWidget; - Style: PGtkStyle; -begin - Widget := gtk_window_new(GTK_WINDOW_TOPLEVEL); - Style := gtk_rc_get_style(Widget); - Result := @(Style^.bg[State]); - gtk_widget_destroy(Widget); -end; -function GetDefaultBackgroundColor(Widget: TGTKControl; State: integer): PGdkColor; -var Style: PGtkStyle; +function GetDefaultBackgroundColor(Widget: TGTKControl; State: TGtkStateFlags): PGdkRGBA; +var StyleContext: PGtkStyleContext; + Value: PGdkRGBA; begin - Style := gtk_rc_get_style(Widget.FWidget); - Result := @(Style^.bg[State]); + Value := nil; + StyleContext := gtk_widget_get_style_context(Widget.FWidget); + gtk_style_context_get(StyleContext, State, [GTK_STYLE_PROPERTY_BACKGROUND_COLOR, @Value, nil]); + Result := Value; end; -*) (********************************************************************************************************************************) (* -function GetDefaultBaseColor(State: integer): PGdkColor; +function GetDefaultBaseColor(State: TGtkStateFlags): PGdkRGBA; var Widget: PGtkWidget; Style: PGtkStyle; begin @@ -139,7 +139,7 @@ begin gtk_widget_destroy(Widget); end; -function GetDefaultBaseColor(Widget: TGTKControl; State: integer): PGdkColor; +function GetDefaultBaseColor(Widget: TGTKControl; State: TGtkStateFlags): PGdkRGBA; var Style: PGtkStyle; begin Style := gtk_rc_get_style(Widget.FWidget); @@ -148,24 +148,17 @@ end; *) (********************************************************************************************************************************) -(* -function GetDefaultTextColor(State: integer): PGdkColor; -var Widget: PGtkWidget; - Style: PGtkStyle; -begin - Widget := gtk_window_new(GTK_WINDOW_TOPLEVEL); - Style := gtk_rc_get_style(Widget); - Result := @(Style^.text[State]); - gtk_widget_destroy(Widget); -end; -function GetDefaultTextColor(Widget: TGTKControl; State: integer): PGdkColor; -var Style: PGtkStyle; +function GetDefaultTextColor(Widget: TGTKControl; State: TGtkStateFlags): PGdkRGBA; +var StyleContext: PGtkStyleContext; + Value: PGdkRGBA; begin - Style := gtk_rc_get_style(Widget.FWidget); - Result := @(Style^.text[State]); + Value := nil; + StyleContext := gtk_widget_get_style_context(Widget.FWidget); + gtk_style_context_get(StyleContext, State, [GTK_STYLE_PROPERTY_COLOR, @Value, nil]); + Result := Value; end; -*) + (********************************************************************************************************************************) (* @@ -218,6 +211,26 @@ end; *) (********************************************************************************************************************************) +function GDKRGBAToString(Color: PGdkRGBA): string; +begin + Result := ''; + if Assigned(Color) then Result := String(gdk_rgba_to_string(Color)); +end; + +function StringToGDKRGBA(Str: string): PGdkRGBA; +var Value: TGdkRGBA; +begin + if Length(Str) < 1 then begin + Result := nil; + Exit; + end; + Initialize(Value); + if gdk_rgba_parse(@Value, PChar(Str)) then Result := gdk_rgba_copy(@Value) + else begin + g_log(PChar('tuxcmd'), [G_LOG_LEVEL_WARNING], 'Failed to parse color string "%s"', [PChar(Str)]); + Result := nil; + end; +end; function ValidateColorString(const Color: string): boolean; var rgba: TGdkRGBA; @@ -225,4 +238,35 @@ begin Result := gdk_rgba_parse(@rgba, PChar(Color)); end; +(********************************************************************************************************************************) + +function PangoFontDescToCSS(const PangoFontDesc: string): string; +var font_desc: PPangoFontDescription; + s: string; + val: Pgchar; + size: gint; +begin + s := ''; + font_desc := pango_font_description_from_string(PChar(PangoFontDesc)); + if not Assigned(font_desc) then begin + Result := ''; + Exit; + end; + val := pango_font_description_get_family(font_desc); + if Assigned(val) then s := s + 'font-family: ' + string(val) + '; '; + size := pango_font_description_get_size(font_desc); + if size > 0 then begin + if pango_font_description_get_size_is_absolute(font_desc) + then s := s + 'font-size: ' + IntToStr(size) + 'px; ' + else s := s + 'font-size: ' + IntToStr(Trunc(pango_units_to_double(size))) + 'pt; '; + end; + case pango_font_description_get_style(font_desc) of + PANGO_STYLE_NORMAL: ; + PANGO_STYLE_OBLIQUE: s := s + 'font-style: oblique; '; + PANGO_STYLE_ITALIC: s := s + 'font-style: italic; '; + end; + pango_font_description_free(font_desc); + Result := s; +end; + end. diff --git a/libgtk_kylix/GTKView.pas b/libgtk_kylix/GTKView.pas index b971e7d..1ac742b 100644 --- a/libgtk_kylix/GTKView.pas +++ b/libgtk_kylix/GTKView.pas @@ -210,6 +210,7 @@ type function GetSearchColumn: integer; function GetSortColumnID: integer; function GetSortOrder: TGTKTreeViewSortOrder; + function GetFixedHeightMode: boolean; procedure SetSelectionMode(Value: TGTKSelectionMode); procedure SetShowHeaders(Value: boolean); procedure SetRulesHint(Value: boolean); @@ -218,6 +219,7 @@ type procedure SetSearchColumn(Value: integer); procedure SetSortColumnID(Value: integer); procedure SetSortOrder(Value: TGTKTreeViewSortOrder); + procedure SetFixedHeightMode(Value: boolean); protected public FSelection: PGtkTreeSelection; @@ -244,6 +246,7 @@ type property CellDataFunc: TGTKCellDataFunc read FCellDataFunc write FCellDataFunc; property FromSortedCoversionFunc: TGTKSortCoversionFunc read FFromSortedConvFunc write FFromSortedConvFunc; property ToSortedCoversionFunc: TGTKSortCoversionFunc read FToSortedConvFunc write FToSortedConvFunc; + property FixedHeightMode: boolean read GetFixedHeightMode write SetFixedHeightMode; end; (****************************************** TGTKLISTVIEW ************************************************************************) @@ -255,6 +258,9 @@ type FSortable: boolean; FCompareFunc: TGTKTreeViewCompareFunc; FOnColumnsChanged: TNotifyEvent; + FChangedSignalHandlerID: gulong; + FRowActivatedSignalHandlerID: gulong; + FColumnsChangedSignalHandlerID: gulong; protected FListItems: TGTKListItems; procedure Recreate; @@ -291,6 +297,7 @@ begin FOnSelectionChanged := nil; FToSortedConvFunc := nil; FFromSortedConvFunc := nil; + FSelection := nil; end; destructor TGTKView.Destroy; @@ -388,6 +395,16 @@ begin gtk_tree_sortable_set_sort_column_id(PGtkTreeSortable(FTreeModelSort), Value, TGtkSortType(GetSortOrder)); end; +function TGTKView.GetFixedHeightMode: boolean; +begin + Result := gtk_tree_view_get_fixed_height_mode(PGtkTreeView(FWidget)); +end; + +procedure TGTKView.SetFixedHeightMode(Value: boolean); +begin + gtk_tree_view_set_fixed_height_mode(PGtkTreeView(FWidget), Value); +end; + procedure TGTKView.ConvertChildToPath(var Path: PGtkTreePath); var NewPath: PGtkTreePath; begin @@ -471,6 +488,9 @@ end; constructor TGTKListView.Create(AOwner: TComponent); begin inherited Create(AOwner); + FChangedSignalHandlerID := 0; + FRowActivatedSignalHandlerID := 0; + FColumnsChangedSignalHandlerID := 0; FListItems := TGTKListItems.Create(Self); FSortable := False; FCompareFunc := nil; @@ -479,6 +499,9 @@ end; destructor TGTKListView.Destroy; begin +// if FChangedSignalHandlerID > 0 then g_signal_handler_disconnect(PGObject(FSelection), FChangedSignalHandlerID); +// if FRowActivatedSignalHandlerID > 0 then g_signal_handler_disconnect(PGObject(FWidget), FRowActivatedSignalHandlerID); +// if FColumnsChangedSignalHandlerID > 0 then g_signal_handler_disconnect(PGObject(FWidget), FColumnsChangedSignalHandlerID); FListItems.Free; inherited Destroy; end; @@ -517,9 +540,9 @@ begin FWidget := gtk_tree_view_new_with_model(PGtkTreeModel(FTreeModelSort)); end; FSelection := gtk_tree_view_get_selection(PGtkTreeView(FWidget)); - g_signal_connect_data(PGObject(FSelection), 'changed', TGCallback(@TGTKListView_changed), Self, nil, G_CONNECT_DEFAULT); - g_signal_connect_data(PGObject(FWidget), 'row-activated', TGCallback(@TGTKListView_row_activated), Self, nil, G_CONNECT_DEFAULT); - g_signal_connect_data(PGObject(FWidget), 'columns-changed', TGCallback(@TGTKListView_columns_changed), Self, nil, [G_CONNECT_AFTER]); + FChangedSignalHandlerID := g_signal_connect_data(PGObject(FSelection), 'changed', TGCallback(@TGTKListView_changed), Self, nil, G_CONNECT_DEFAULT); + FRowActivatedSignalHandlerID := g_signal_connect_data(PGObject(FWidget), 'row-activated', TGCallback(@TGTKListView_row_activated), Self, nil, G_CONNECT_DEFAULT); + FColumnsChangedSignalHandlerID := g_signal_connect_data(PGObject(FWidget), 'columns-changed', TGCallback(@TGTKListView_columns_changed), Self, nil, [G_CONNECT_AFTER]); FTreeModel := gtk_tree_view_get_model(PGtkTreeView(FWidget)); Show; end; @@ -663,7 +686,7 @@ end; function TGTKListItems.GetItem(Index: longint): TGTKListItem; begin Result := TGTKListItem(FList[Index]); - Result.FIndex := Index; +// Result.FIndex := Index; end; procedure TGTKListItems.SetItem(Index: longint; Value: TGTKListItem); @@ -672,11 +695,12 @@ begin end; function TGTKListItems.Add: TGTKListItem; +var Item: TGTKListItem; begin - Result := TGTKListItem.Create(Self); - Result.FIndex := GetCount; -// Insert(GetCount, Result); - Append(Result); + Item := TGTKListItem.Create(Self); + Item.FIndex := GetCount; + Append(Item); + Result := Item; end; function TGTKListItems.GetCount: longint; @@ -691,16 +715,17 @@ begin end; procedure TGTKListItems.Delete(Index: longint); -var x: pointer; +var x: TGTKListItem; Iter: TGtkTreeIter; begin - x := FList[Index]; + Initialize(Iter); + x := TGTKListItem(FList[Index]); if gtk_tree_model_get_iter_from_string(PGtkTreeModel(FStore), @Iter, PChar(IntToStr(Index))) then begin // (FOwner as TGTKView).CovertSortableIter(Iter); gtk_list_store_remove(FStore, @Iter); - end; + end else writeln(' iter invalid!!!'); FList.Delete(Index); - TObject(x).Free; + x.Free; end; procedure TGTKListItems.Insert(Index: longint; Item: TGTKListItem); @@ -713,12 +738,217 @@ end; procedure TGTKListItems.Append(Item: TGTKListItem); var Iter: TGtkTreeIter; begin + Initialize(Iter); FList.Add(Item); gtk_list_store_append(FStore, @Iter); end; (********************************************************************************************************************************) (********************************************************************************************************************************) +constructor TGTKListItem.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FOwner := AOwner; + FData := nil; +end; + +destructor TGTKListItem.Destroy; +begin + inherited Destroy; +end; + +function TGTKListItem.AsString(Index: longint): string; +var Iter: TGtkTreeIter; + Val: Pgchar; +begin + Result := ''; + Val := nil; + if gtk_tree_model_get_iter_from_string(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, PChar(IntToStr(FIndex))) then + begin + gtk_tree_model_get(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, [Index, @Val, -1]); + if Assigned(Val) then Result := String(Val); + end; +end; + +function TGTKListItem.AsInteger(Index: longint): integer; +var Iter: TGtkTreeIter; + Val: glong; +begin + Result := 0; + Val := 0; + if gtk_tree_model_get_iter_from_string(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, PChar(IntToStr(FIndex))) then + begin + gtk_tree_model_get(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, [Index, @Val, -1]); + Result := Val; + end; +end; + +function TGTKListItem.AsPointer(Index: longint): pointer; +var Iter: TGtkTreeIter; + Val: Pointer; +begin + Result := nil; + Val := nil; + if gtk_tree_model_get_iter_from_string(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, PChar(IntToStr(FIndex))) then + begin + gtk_tree_model_get(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, [Index, @Val, -1]); + Result := Val; + end; +end; + +function TGTKListItem.AsBoolean(Index: longint): boolean; +var Iter: TGtkTreeIter; + Val: gboolean; +begin + Result := False; + Val := False; + if gtk_tree_model_get_iter_from_string(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, PChar(IntToStr(FIndex))) then + begin + gtk_tree_model_get(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, [Index, @Val, -1]); + Result := Val; + end; +end; + +procedure TGTKListItem.SetValue(Index: longint; Value: string); +var Iter: TGtkTreeIter; +begin + if gtk_tree_model_get_iter_from_string(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, PChar(IntToStr(FIndex))) + then gtk_list_store_set((FOwner as TGTKListItems).FStore, @Iter, [Index, PChar(Value), -1]); +end; + +procedure TGTKListItem.SetValue(Index: longint; Value: integer); +var Iter: TGtkTreeIter; +begin + if gtk_tree_model_get_iter_from_string(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, PChar(IntToStr(FIndex))) + then gtk_list_store_set((FOwner as TGTKListItems).FStore, @Iter, [Index, glong(Value), -1]); +end; + +procedure TGTKListItem.SetValue(Index: longint; Value: pointer); +var Iter: TGtkTreeIter; +begin + if gtk_tree_model_get_iter_from_string(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, PChar(IntToStr(FIndex))) + then gtk_list_store_set((FOwner as TGTKListItems).FStore, @Iter, [Index, gpointer(Value), -1]); +end; + +procedure TGTKListItem.SetValue(Index: longint; Value: boolean); +var Iter: TGtkTreeIter; +begin + if gtk_tree_model_get_iter_from_string(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, PChar(IntToStr(FIndex))) + then gtk_list_store_set((FOwner as TGTKListItems).FStore, @Iter, [Index, gboolean(Value), -1]); +end; + +function TGTKListItem.GetSelected: boolean; +var Iter: TGtkTreeIter; +begin + Result := False; + if gtk_tree_model_get_iter_from_string(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, PChar(IntToStr(FIndex))) then begin +// ((FOwner as TGTKListItems).FOwner as TGTKView).ConvertSortableIter(Iter); + Result := gtk_tree_selection_iter_is_selected(((FOwner as TGTKListItems).FOwner as TGTKView).FSelection, @Iter); + end; +end; + +procedure TGTKListItem.SetSelected(Value: boolean); +var Iter, NewIter: TGtkTreeIter; +begin + try + if gtk_tree_model_get_iter_from_string(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, PChar(IntToStr(FIndex))) then begin + if Assigned(((FOwner as TGTKListItems).FOwner as TGTKView).FTreeModelSort) then begin + gtk_tree_model_sort_convert_child_iter_to_iter(((FOwner as TGTKListItems).FOwner as TGTKView).FTreeModelSort, @NewIter, @Iter); + Iter := NewIter; + end; + if Value then gtk_tree_selection_select_iter(((FOwner as TGTKListItems).FOwner as TGTKView).FSelection, @Iter) + else gtk_tree_selection_unselect_iter(((FOwner as TGTKListItems).FOwner as TGTKView).FSelection, @Iter); + end; + except end; +end; + +procedure TGTKListItem.SetCursor(const FocusColumnNo: integer; const StartEditing, UseAlignment: boolean; const AlignX, AlignY: Double); +var Path: PGtkTreePath; + Column: PGtkTreeViewColumn; +// Renderer: PGtkCellRenderer; + i : integer; +begin + Path := gtk_tree_path_new_from_string(PChar(IntToStr(FIndex))); + if not Assigned(Path) then Exit; + ((FOwner as TGTKListItems).FOwner as TGTKView).ConvertChildToPath(Path); + if not Assigned(Path) then Exit; + + Column := ((FOwner as TGTKListItems).FOwner as TGTKView).Columns[FocusColumnNo].FColumn; +// Renderer := ((FOwner as TGTKListItems).FOwner as TGTKView).Columns[FocusColumnNo].FRenderer; + + gtk_tree_view_set_cursor(PGtkTreeView(((FOwner as TGTKListItems).FOwner as TGTKView).FWidget), Path, Column, StartEditing); +// gtk_tree_view_set_cursor(PGtkTreeView(((FOwner as TGTKListItems).FOwner as TGTKView).FWidget), Path, Column, StartEditing); +// gtk_tree_view_set_cursor_on_cell(PGtkTreeView(((FOwner as TGTKListItems).FOwner as TGTKView).FWidget), Path, Column, Renderer, StartEditing); + gtk_tree_view_scroll_to_cell(PGtkTreeView(((FOwner as TGTKListItems).FOwner as TGTKView).FWidget), Path, nil, UseAlignment, AlignX, AlignY); + + gtk_tree_path_free(Path); +end; + +procedure TGTKListItem.StartEditing(ColumnNo: integer); +var CellEditable: PGtkCellEditable; + Path: PGtkTreePath; + Column: PGtkTreeViewColumn; + BackgroundRect, CellRect: TGdkRectangle; +begin + Path := gtk_tree_path_new_from_string(PChar(IntToStr(FIndex))); + if not Assigned(Path) then Exit; + ((FOwner as TGTKListItems).FOwner as TGTKView).ConvertChildToPath(Path); + if not Assigned(Path) then Exit; + Column := ((FOwner as TGTKListItems).FOwner as TGTKView).Columns[ColumnNo].FColumn; + gtk_tree_view_get_background_area(PGtkTreeView(((FOwner as TGTKListItems).FOwner as TGTKView).FWidget), Path, Column, @BackgroundRect); + gtk_tree_view_get_cell_area(PGtkTreeView(((FOwner as TGTKListItems).FOwner as TGTKView).FWidget), Path, Column, @CellRect); + + gtk_tree_view_column_focus_cell(Column, ((FOwner as TGTKListItems).FOwner as TGTKView).Columns[ColumnNo].FRenderer); + CellEditable := gtk_cell_renderer_start_editing(((FOwner as TGTKListItems).FOwner as TGTKView).Columns[ColumnNo].FRenderer, + nil, ((FOwner as TGTKListItems).FOwner as TGTKView).FWidget, PChar(PChar(IntToStr(FIndex))), + @BackgroundRect, @CellRect, []); + gtk_widget_show(PGtkWidget(CellEditable)); +// gtk_cell_editable_start_editing(CellEditable, nil); + + + gtk_tree_path_free(Path); +end; + +procedure TGTKListItem.RedrawRow; +var Rect, BackgroundRect: TGdkRectangle; + Path: PGtkTreePath; + Column: PGtkTreeViewColumn; +begin +Exit; + Path := gtk_tree_path_new_from_string(PChar(IntToStr(FIndex))); + if not Assigned(Path) then Exit; + ((FOwner as TGTKListItems).FOwner as TGTKView).ConvertChildToPath(Path); + if not Assigned(Path) then Exit; + Column := ((FOwner as TGTKListItems).FOwner as TGTKView).Columns[0].FColumn; + gtk_tree_view_get_background_area(PGtkTreeView(((FOwner as TGTKListItems).FOwner as TGTKView).FWidget), Path, Column, @BackgroundRect); + + Rect.x := 0; + Rect.width := gtk_widget_get_allocated_width(((FOwner as TGTKListItems).FOwner as TGTKView).FWidget); + Rect.y := BackgroundRect.y; + Rect.height := BackgroundRect.height; + gdk_window_invalidate_rect(gtk_tree_view_get_bin_window(PGtkTreeView(((FOwner as TGTKListItems).FOwner as TGTKView).FWidget)), @Rect, True); + + gtk_tree_path_free(Path); +end; + +function TGTKListItem.IsVisible: boolean; +var CellRect, VisibleRect: TGdkRectangle; + Path: PGtkTreePath; +begin + Result := False; + Exit; + gtk_tree_view_get_visible_rect(PGtkTreeView(((FOwner as TGTKListItems).FOwner as TGTKView).FWidget), @VisibleRect); + Path := gtk_tree_path_new_from_string(PChar(IntToStr(FIndex))); + if not Assigned(Path) then Exit; + ((FOwner as TGTKListItems).FOwner as TGTKView).ConvertChildToPath(Path); + if not Assigned(Path) then Exit; + gtk_tree_view_get_background_area(PGtkTreeView(((FOwner as TGTKListItems).FOwner as TGTKView).FWidget), Path, nil, @CellRect); + gtk_tree_path_free(Path); + Result := (CellRect.y > VisibleRect.y) and (CellRect.y + CellRect.height < VisibleRect.y + VisibleRect.height); +end; + +(********************************************************************************************************************************) +(********************************************************************************************************************************) constructor TGTKTreeViewColumns.Create(AOwner: TComponent); begin inherited Create(AOwner); @@ -1108,209 +1338,6 @@ begin g_object_set_property(PGObject(FPixbufRenderer), PChar(AProperty), @AValue); end; -(********************************************************************************************************************************) -(********************************************************************************************************************************) -constructor TGTKListItem.Create(AOwner: TComponent); -begin - inherited Create(AOwner); - FOwner := AOwner; - FData := nil; -end; - -destructor TGTKListItem.Destroy; -begin - inherited Destroy; -end; - -function TGTKListItem.AsString(Index: longint): string; -var Iter: TGtkTreeIter; - AValue: TGValue; -begin - Result := ''; - if gtk_tree_model_get_iter_from_string(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, PChar(IntToStr(FIndex))) then - begin - AValue.g_type := 0; - gtk_tree_model_get_value(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, Index, @AValue); - Result := String(AValue.data[0].v_pointer); - end; -end; - -function TGTKListItem.AsInteger(Index: longint): integer; -var Iter: TGtkTreeIter; - AValue: TGValue; -begin - Result := 0; - if gtk_tree_model_get_iter_from_string(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, PChar(IntToStr(FIndex))) then - begin - AValue.g_type := 0; - gtk_tree_model_get_value(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, Index, @AValue); - Result := AValue.data[0].v_long; - end; -end; - -function TGTKListItem.AsPointer(Index: longint): pointer; -var Iter: TGtkTreeIter; - AValue: TGValue; -begin - Result := nil; - if gtk_tree_model_get_iter_from_string(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, PChar(IntToStr(FIndex))) then - begin - AValue.g_type := 0; - gtk_tree_model_get_value(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, Index, @AValue); - Result := AValue.data[0].v_pointer; - end; -end; - -function TGTKListItem.AsBoolean(Index: longint): boolean; -var Iter: TGtkTreeIter; - AValue: TGValue; -begin - Result := False; - if gtk_tree_model_get_iter_from_string(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, PChar(IntToStr(FIndex))) then - begin - AValue.g_type := 0; - gtk_tree_model_get_value(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, Index, @AValue); - Result := boolean(AValue.data[0].v_int); - end; -end; - -procedure TGTKListItem.SetValue(Index: longint; Value: string); -var Iter: TGtkTreeIter; -begin - if gtk_tree_model_get_iter_from_string(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, PChar(IntToStr(FIndex))) - then gtk_list_store_set((FOwner as TGTKListItems).FStore, @Iter, [Index, PChar(Value), -1]); -end; - -procedure TGTKListItem.SetValue(Index: longint; Value: integer); -var Iter: TGtkTreeIter; -begin - if gtk_tree_model_get_iter_from_string(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, PChar(IntToStr(FIndex))) - then gtk_list_store_set((FOwner as TGTKListItems).FStore, @Iter, [Index, Value, -1]); -end; - -procedure TGTKListItem.SetValue(Index: longint; Value: pointer); -var Iter: TGtkTreeIter; -begin - if gtk_tree_model_get_iter_from_string(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, PChar(IntToStr(FIndex))) - then gtk_list_store_set((FOwner as TGTKListItems).FStore, @Iter, [Index, Value, -1]); -end; - -procedure TGTKListItem.SetValue(Index: longint; Value: boolean); -var Iter: TGtkTreeIter; -begin - if gtk_tree_model_get_iter_from_string(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, PChar(IntToStr(FIndex))) - then gtk_list_store_set((FOwner as TGTKListItems).FStore, @Iter, [Index, Value, -1]); -end; - -function TGTKListItem.GetSelected: boolean; -var Iter: TGtkTreeIter; -begin - Result := False; - if gtk_tree_model_get_iter_from_string(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, PChar(IntToStr(FIndex))) then begin -// ((FOwner as TGTKListItems).FOwner as TGTKView).ConvertSortableIter(Iter); - Result := gtk_tree_selection_iter_is_selected(((FOwner as TGTKListItems).FOwner as TGTKView).FSelection, @Iter); - end; -end; - -procedure TGTKListItem.SetSelected(Value: boolean); -var Iter, NewIter: TGtkTreeIter; -begin - try - if gtk_tree_model_get_iter_from_string(PGtkTreeModel((FOwner as TGTKListItems).FStore), @Iter, PChar(IntToStr(FIndex))) then begin - if Assigned(((FOwner as TGTKListItems).FOwner as TGTKView).FTreeModelSort) then begin - gtk_tree_model_sort_convert_child_iter_to_iter(((FOwner as TGTKListItems).FOwner as TGTKView).FTreeModelSort, @NewIter, @Iter); - Iter := NewIter; - end; - if Value then gtk_tree_selection_select_iter(((FOwner as TGTKListItems).FOwner as TGTKView).FSelection, @Iter) - else gtk_tree_selection_unselect_iter(((FOwner as TGTKListItems).FOwner as TGTKView).FSelection, @Iter); - end; - except end; -end; - -procedure TGTKListItem.SetCursor(const FocusColumnNo: integer; const StartEditing, UseAlignment: boolean; const AlignX, AlignY: Double); -var Path: PGtkTreePath; - Column: PGtkTreeViewColumn; -// Renderer: PGtkCellRenderer; - i : integer; -begin - Path := gtk_tree_path_new_from_string(PChar(IntToStr(FIndex))); - if not Assigned(Path) then Exit; - ((FOwner as TGTKListItems).FOwner as TGTKView).ConvertChildToPath(Path); - if not Assigned(Path) then Exit; - - Column := ((FOwner as TGTKListItems).FOwner as TGTKView).Columns[FocusColumnNo].FColumn; -// Renderer := ((FOwner as TGTKListItems).FOwner as TGTKView).Columns[FocusColumnNo].FRenderer; - - for i := 1 to 2 do gtk_main_iteration_do(False); // This ugly piece of code HAVE TO BE HERE due some focus-related problems in GtkTreeView - gtk_tree_view_set_cursor(PGtkTreeView(((FOwner as TGTKListItems).FOwner as TGTKView).FWidget), Path, Column, StartEditing); -// gtk_tree_view_set_cursor(PGtkTreeView(((FOwner as TGTKListItems).FOwner as TGTKView).FWidget), Path, Column, StartEditing); -// gtk_tree_view_set_cursor_on_cell(PGtkTreeView(((FOwner as TGTKListItems).FOwner as TGTKView).FWidget), Path, Column, Renderer, StartEditing); - gtk_tree_view_scroll_to_cell(PGtkTreeView(((FOwner as TGTKListItems).FOwner as TGTKView).FWidget), Path, nil, UseAlignment, AlignX, AlignY); - - gtk_tree_path_free(Path); -end; - -procedure TGTKListItem.StartEditing(ColumnNo: integer); -var CellEditable: PGtkCellEditable; - Path: PGtkTreePath; - Column: PGtkTreeViewColumn; - BackgroundRect, CellRect: TGdkRectangle; -begin - Path := gtk_tree_path_new_from_string(PChar(IntToStr(FIndex))); - if not Assigned(Path) then Exit; - ((FOwner as TGTKListItems).FOwner as TGTKView).ConvertChildToPath(Path); - if not Assigned(Path) then Exit; - Column := ((FOwner as TGTKListItems).FOwner as TGTKView).Columns[ColumnNo].FColumn; - gtk_tree_view_get_background_area(PGtkTreeView(((FOwner as TGTKListItems).FOwner as TGTKView).FWidget), Path, Column, @BackgroundRect); - gtk_tree_view_get_cell_area(PGtkTreeView(((FOwner as TGTKListItems).FOwner as TGTKView).FWidget), Path, Column, @CellRect); - - gtk_tree_view_column_focus_cell(Column, ((FOwner as TGTKListItems).FOwner as TGTKView).Columns[ColumnNo].FRenderer); - CellEditable := gtk_cell_renderer_start_editing(((FOwner as TGTKListItems).FOwner as TGTKView).Columns[ColumnNo].FRenderer, - nil, ((FOwner as TGTKListItems).FOwner as TGTKView).FWidget, PChar(PChar(IntToStr(FIndex))), - @BackgroundRect, @CellRect, []); - gtk_widget_show(PGtkWidget(CellEditable)); -// gtk_cell_editable_start_editing(CellEditable, nil); - - - gtk_tree_path_free(Path); -end; - -procedure TGTKListItem.RedrawRow; -var Rect, BackgroundRect: TGdkRectangle; - Path: PGtkTreePath; - Column: PGtkTreeViewColumn; -begin - Path := gtk_tree_path_new_from_string(PChar(IntToStr(FIndex))); - if not Assigned(Path) then Exit; - ((FOwner as TGTKListItems).FOwner as TGTKView).ConvertChildToPath(Path); - if not Assigned(Path) then Exit; - Column := ((FOwner as TGTKListItems).FOwner as TGTKView).Columns[0].FColumn; - gtk_tree_view_get_background_area(PGtkTreeView(((FOwner as TGTKListItems).FOwner as TGTKView).FWidget), Path, Column, @BackgroundRect); - - Rect.x := 0; - Rect.width := gtk_widget_get_allocated_width(((FOwner as TGTKListItems).FOwner as TGTKView).FWidget); - Rect.y := BackgroundRect.y; - Rect.height := BackgroundRect.height; - gdk_window_invalidate_rect(gtk_tree_view_get_bin_window(PGtkTreeView(((FOwner as TGTKListItems).FOwner as TGTKView).FWidget)), @Rect, True); - - gtk_tree_path_free(Path); -end; - -function TGTKListItem.IsVisible: boolean; -var CellRect, VisibleRect: TGdkRectangle; - Path: PGtkTreePath; -begin - Result := False; - gtk_tree_view_get_visible_rect(PGtkTreeView(((FOwner as TGTKListItems).FOwner as TGTKView).FWidget), @VisibleRect); - Path := gtk_tree_path_new_from_string(PChar(IntToStr(FIndex))); - if not Assigned(Path) then Exit; - ((FOwner as TGTKListItems).FOwner as TGTKView).ConvertChildToPath(Path); - if not Assigned(Path) then Exit; - gtk_tree_view_get_background_area(PGtkTreeView(((FOwner as TGTKListItems).FOwner as TGTKView).FWidget), Path, nil, @CellRect); - gtk_tree_path_free(Path); - Result := (CellRect.y > VisibleRect.y) and (CellRect.y + CellRect.height < VisibleRect.y + VisibleRect.height); -end; - (********************************************************************************************************************************) (********************************************************************************************************************************) |
