summaryrefslogtreecommitdiff
path: root/UMain.pas
diff options
context:
space:
mode:
authorTomas Bzatek <tbzatek@redhat.com>2025-01-04 20:41:26 +0100
committerTomas Bzatek <tbzatek@redhat.com>2025-11-27 21:42:57 +0100
commit90db8b6652f73ddc335922d3a7c593878d83c45e (patch)
tree6b3f8ed57d4dc3358c2965bf41f6e613b8b80bf0 /UMain.pas
parent63ff1bea9bb1e87a7e2643f680d04f2b9c00d072 (diff)
downloadtuxcmd-90db8b6652f73ddc335922d3a7c593878d83c45e.tar.xz
Basic ListView CSS styling
Diffstat (limited to 'UMain.pas')
-rw-r--r--UMain.pas209
1 files changed, 103 insertions, 106 deletions
diff --git a/UMain.pas b/UMain.pas
index 0c17c7f..87df6c0 100644
--- a/UMain.pas
+++ b/UMain.pas
@@ -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;