diff options
| author | Tomas Bzatek <tbzatek@users.sourceforge.net> | 2008-06-07 20:34:49 +0200 |
|---|---|---|
| committer | Tomas Bzatek <tbzatek@users.sourceforge.net> | 2008-06-07 20:34:49 +0200 |
| commit | ecde167da74c86bc047aaf84c5e548cf65a5da98 (patch) | |
| tree | a015dfda84f28a65811e3aa0d369f8f211ec8c60 /UViewer.pas | |
| download | tuxcmd-ecde167da74c86bc047aaf84c5e548cf65a5da98.tar.xz | |
Initial commitv0.6.36release-0.6.36-dev
Diffstat (limited to 'UViewer.pas')
| -rw-r--r-- | UViewer.pas | 451 |
1 files changed, 451 insertions, 0 deletions
diff --git a/UViewer.pas b/UViewer.pas new file mode 100644 index 0000000..d7d1c4c --- /dev/null +++ b/UViewer.pas @@ -0,0 +1,451 @@ +(* + Tux Commander - UViewer - Internal viewer + Copyright (C) 2008 Tomas Bzatek <tbzatek@users.sourceforge.net> + Check for updates on tuxcmd.sourceforge.net + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + WARNING: This is highly experimental feature, use with caution! +*) +unit UViewer; + +interface + +uses + glib2, gdk2, gtk2, pango, + SysUtils, Types, Classes, Variants, GTKControls, GTKForms, GTKUtils, GTKDialogs, GTKPixbuf, GTKClasses, GTKExtCtrls, GTKConsts, + GTKText; + +type + TFViewer = class(TGTKForm) +// FDrawingArea: TGTKControl; + TextView: TGTKTextView; + ScrolledWindow: TGTKScrolledWindow; + procedure FormCreate(Sender: TObject); override; + procedure FormDestroy(Sender: TObject); + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure FormKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean); +// procedure DrawingAreaKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean); + procedure TextViewKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean); + private +// LineHeight, NumLines: integer; + LineBuffer: TStringList; + protected + AThread: TThread; + public + function LoadFile(FileName: string): boolean; + end; + + TViewerThread = class(TThread) + private +// procedure DoIt; + protected + procedure Execute; override; + public + AViewer: TFViewer; + constructor Create(Parent: TComponent); + destructor Destroy; override; + function LoadFile(FileName: string): boolean; + end; + +var + FViewer: TFViewer; + +implementation + +uses UCoreUtils, UCoreClasses, UConfig, DateUtils, Libc; + + + +// function expose_event_callback(AWidget: PGtkWidget; event: PGdkEventExpose; data: gpointer): gboolean; cdecl; forward; +function scroll_event_callback(widget: PGtkWidget; event: PGdkEventScroll; user_data: gpointer): gboolean; cdecl; forward; + + +procedure TFViewer.FormCreate(Sender: TObject); +begin + SetDefaultSize(700, 500); + Caption := 'TuxView'; + BorderWidth := 5; + AThread := nil; + + ScrolledWindow := TGTKScrolledWindow.Create(Self); + ScrolledWindow.HorizScrollBarPolicy := sbAutomatic; + ScrolledWindow.VertScrollBarPolicy := sbAutomatic; + ScrolledWindow.ShadowType := stShadowIn; + g_signal_connect(G_OBJECT(ScrolledWindow.FWidget), 'scroll-event', G_CALLBACK (@scroll_event_callback), Self); + AddControl(ScrolledWindow); +// ClientArea.AddControl(ScrolledWindow); + +(* + FDrawingArea := TGTKControl.Create(Self); + FDrawingArea.FWidget := gtk_drawing_area_new; + gtk_widget_set_events(FDrawingArea.FWidget, GDK_EXPOSURE_MASK or GDK_BUTTON_PRESS_MASK or GDK_POINTER_MOTION_MASK or GDK_KEY_PRESS_MASK); + gtk_widget_set_size_request(FDrawingArea.FWidget, 10000, 40000); + g_signal_connect(G_OBJECT(FDrawingArea.FWidget), 'expose_event', G_CALLBACK (@expose_event_callback), Self); +// g_signal_connect_after(G_OBJECT(FDrawingArea.FWidget), 'key_press_event', G_CALLBACK (@key_press_event_callback), NULL); + gtk_widget_set(FDrawingArea.FWidget, 'can_focus', TRUE, 0); + gtk_widget_set(FDrawingArea.FWidget, 'can_default', TRUE, 0); + gtk_widget_show(FDrawingArea.FWidget); + FDrawingArea.OnKeyDown := DrawingAreaKeyDown; + + ScrolledWindow.AddWithViewPort(FDrawingArea); + FDrawingArea.SetFocus; +*) + + TextView := TGTKTextView.Create(Self); + TextView.CursorVisible := False; + TextView.ReadOnly := True; + TextView.OnKeyDown := TextViewKeyDown; + + ScrolledWindow.AddControl(TextView); + TextView.SetFocus; + + // ****************** + + OnKeyDown := FormKeyDown; + OnDestroy := FormDestroy; + OnClose := FormClose; +end; + +procedure TFViewer.FormKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean); +begin + if Key = GDK_ESCAPE then Close; +end; + +procedure TFViewer.FormClose(Sender: TObject; var Action: TCloseAction); +begin + Action := caFree; + SetParent(nil); + if Assigned(FWidget) and GTK_IS_WIDGET(FWidget) then gtk_widget_destroy(PGtkWidget(FWidget)); +// AThread.Terminate; +// ModalResult := mbOK; +end; + +procedure TFViewer.FormDestroy(Sender: TObject); +begin + try + LineBuffer.Free; + except end; +end; + + +procedure smooth_scroll(adj: PGtkAdjustment; dest_value: Double; PageScroll: boolean); +var increment, val: Double; + i, x: integer; + timer: PGTimer; + microseconds: gulong; + dur, st: integer; +begin + if gtk_adjustment_get_value(adj) = dest_value then Exit; + if not ConfUseSmoothScrolling then begin + gtk_adjustment_set_value(adj, dest_value); + Exit; + end; + + if not PageScroll then begin + dur := SMOOTH_SCROLL_DURATION; + st := SMOOTH_SCROLL_STEPS; + end else begin + dur := SMOOTH_SCROLL_DURATION_PAGE; + st := SMOOTH_SCROLL_STEPS_PAGE; + end; + + timer := g_timer_new; + increment := (dest_value - gtk_adjustment_get_value(adj)) / st; + val := gtk_adjustment_get_value(adj); + +// DebugMsg(['Start value ', val]); + i := 1; + x := 0; + g_timer_start(timer); + repeat + g_timer_elapsed(timer, @microseconds); + if (microseconds > i*1000*dur / st) and (i < st) then begin + val := val + increment; + gtk_adjustment_set_value(adj, val); +// DebugMsg(['Setting value to ', val]); + Inc(i); + end; + gdk_window_process_all_updates; + Inc(x); + usleep(100); + until (microseconds div 1000) > dur; + gtk_adjustment_set_value(adj, dest_value); + gdk_window_process_all_updates; +// DebugMsg(['End value ', dest_value]); + g_timer_stop(timer); + +{ g_timer_elapsed(timer, @microseconds); + DebugMsg(['Smooth scroll: required = ', dur, 'ms, elapsed = ', Integer(microseconds div 1000), 'ms, iterations = ', x]); } + g_timer_destroy(timer); +end; + + +procedure TFViewer.TextViewKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean); +var vadj, hadj: PGtkAdjustment; + x: Double; +begin + vadj := gtk_scrolled_window_get_vadjustment(PGtkScrolledWindow(ScrolledWindow.FWidget)); + hadj := gtk_scrolled_window_get_hadjustment(PGtkScrolledWindow(ScrolledWindow.FWidget)); +// debugmsg(['lower = ', adj^.lower, ', upper = ', adj^.upper, ', value = ', x, ', page_size = ', adj^.page_size]); + Accept := False; + + case Key of + GDK_HOME: begin + smooth_scroll(vadj, 0, True); + smooth_scroll(hadj, 0, True); + end; + GDK_END: begin + smooth_scroll(vadj, vadj^.upper - vadj^.page_size, True); + end; + GDK_Page_Down, GDK_SPACE: begin + x := gtk_adjustment_get_value(vadj) + vadj^.page_increment; + if x + vadj^.page_size > vadj^.upper then x := vadj^.upper - vadj^.page_size; + smooth_scroll(vadj, x, True); + end; + GDK_Page_Up: begin + x := gtk_adjustment_get_value(vadj) - vadj^.page_increment; + if x < 0 then x := 0; + smooth_scroll(vadj, x, True); + end; + GDK_Down: begin + x := gtk_adjustment_get_value(vadj) + vadj^.step_increment; + if x + vadj^.page_size > vadj^.upper then x := vadj^.upper - vadj^.page_size; + smooth_scroll(vadj, x, False); + end; + GDK_Up: begin + x := gtk_adjustment_get_value(vadj) - vadj^.step_increment; + if x < 0 then x := 0; + smooth_scroll(vadj, x, False); + end; + GDK_Right: begin + x := gtk_adjustment_get_value(hadj) + hadj^.step_increment; + if x + hadj^.page_size > hadj^.upper then x := hadj^.upper - hadj^.page_size; + smooth_scroll(hadj, x, False); + end; + GDK_Left: begin + x := gtk_adjustment_get_value(hadj) - hadj^.step_increment; + if x < 0 then x := 0; + smooth_scroll(hadj, x, False); + end; + GDK_W, GDK_Capital_W: if TextView.WrapMode = wmWrapNone then TextView.WrapMode := wmWrapWord + else TextView.WrapMode := wmWrapNone; + GDK_C, GDK_Capital_C, GDK_Insert: if (ssCtrl in Shift) then Accept := True; + GDK_S, GDK_Capital_S: gtk_widget_modify_font(TextView.FWidget, pango_font_description_from_string('Monospace')); + GDK_A, GDK_Capital_A: gtk_widget_modify_font(TextView.FWidget, nil); + + end; +end; + +function scroll_event_callback(widget: PGtkWidget; event: PGdkEventScroll; user_data: gpointer): gboolean; cdecl; +var vadj: PGtkAdjustment; + x: Double; +begin + vadj := gtk_scrolled_window_get_vadjustment(PGtkScrolledWindow(TFViewer(user_data).ScrolledWindow.FWidget)); + Result := True; + + case event^.direction of + GDK_SCROLL_UP: begin + x := gtk_adjustment_get_value(vadj) - 1.5*vadj^.step_increment; + if x < 0 then x := 0; + smooth_scroll(vadj, x, False); + end; + GDK_SCROLL_DOWN: begin + x := gtk_adjustment_get_value(vadj) + 1.5*vadj^.step_increment; + if x + vadj^.page_size > vadj^.upper then x := vadj^.upper - vadj^.page_size; + smooth_scroll(vadj, x, False); + end; + end; +end; + + +(* +procedure TFViewer.DrawingAreaKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean); +var adj: PGtkAdjustment; + x: integer; +begin + Accept := True; + adj := gtk_scrolled_window_get_vadjustment(PGtkScrolledWindow(ScrolledWindow.FWidget)); + case Key of + GDK_ESCAPE: Close; + GDK_Down: begin + x := Trunc(gtk_adjustment_get_value(adj)) + LineHeight; + if x + Trunc(adj^.page_size) > LineHeight * NumLines then x := LineHeight * NumLines - Trunc(adj^.page_size); + gtk_adjustment_set_value(adj, x); + end; + GDK_Up: begin + x := Trunc(gtk_adjustment_get_value(adj)) - LineHeight; + if x < 0 then x := 0; + gtk_adjustment_set_value(adj, x); + end; + GDK_space: begin + x := Trunc(gtk_adjustment_get_value(adj) + adj^.page_increment); + if x + Trunc(adj^.page_size) > LineHeight * NumLines then x := LineHeight * NumLines - Trunc(adj^.page_size); + gtk_adjustment_set_value(adj, x); + end; + end; +{ if event^.keyval = 65364 then begin // Down + adj := gtk_scrolled_window_get_vadjustment(PGtkScrolledWindow(scrolledWindow)); + x := Trunc(gtk_adjustment_get_value(adj)) + LineHeight; + if x + Trunc(adj^.page_size) > LineHeight * NumLines then x := LineHeight * NumLines - Trunc(adj^.page_size); + gtk_adjustment_set_value(adj, x); + end; + if event^.keyval = 65362 then begin // Up + adj := gtk_scrolled_window_get_vadjustment(PGtkScrolledWindow(scrolledWindow)); + x := Trunc(gtk_adjustment_get_value(adj)) - LineHeight; + if x < 0 then x := 0; + gtk_adjustment_set_value(adj, x); + end; + if (event^.keyval = 65366) or (event^.keyval = 32) then begin // PageDown, Space + adj := gtk_scrolled_window_get_vadjustment(PGtkScrolledWindow(scrolledWindow)); + x := Trunc(gtk_adjustment_get_value(adj) + adj^.page_increment); + if x + Trunc(adj^.page_size) > LineHeight * NumLines then x := LineHeight * NumLines - Trunc(adj^.page_size); + gtk_adjustment_set_value(adj, x); + end; + if event^.keyval = 65365 then begin // PageUp + adj := gtk_scrolled_window_get_vadjustment(PGtkScrolledWindow(scrolledWindow)); + x := Trunc(gtk_adjustment_get_value(adj) - adj^.page_increment); + if x < 0 then x := 0; + gtk_adjustment_set_value(adj, x); + end; + if event^.keyval = 65360 then begin // Home + adj := gtk_scrolled_window_get_vadjustment(PGtkScrolledWindow(scrolledWindow)); + gtk_adjustment_set_value(adj, 0); + end; + if event^.keyval = 65367 then begin // End + adj := gtk_scrolled_window_get_vadjustment(PGtkScrolledWindow(scrolledWindow)); + gtk_adjustment_set_value(adj, LineHeight * NumLines - adj^.page_size); + end; } +end; +*) + +(********************************************************************************************************************************) +(* +function expose_event_callback(AWidget: PGtkWidget; event: PGdkEventExpose; data: gpointer): gboolean; cdecl; +var Layout: PPangoLayout; + s: string; + i, LineFrom, LineTo: integer; +var Cursor: PGdkCursor; +begin + // Count the visible lines + LineFrom := (event^.area.y div TFViewer(data).LineHeight) - 1; + if LineFrom < 0 then LineFrom := 0; + LineTo := ((event^.area.y + event^.area.height) div TFViewer(data).LineHeight) + 1; +// if LineTo > MaxLineNum then LineTo := MaxLineNum; + +// DebugMsg(['Rendering lines ', LineFrom, ' - ', LineTo, '; expose_area: [', event^.area.x, ', ', event^.area.y, '] - ', event^.area.width, 'x', event^.area.height]); + + + + gdk_draw_rectangle(PGdkDrawable(Awidget^.window), Awidget^.style^.white_gc, Integer(TRUE), + event^.area.x, event^.area.y, event^.area.width, event^.area.height); + + + + Layout := pango_layout_new(gtk_widget_get_pango_context(Awidget)); + for i := LineFrom to LineTo do begin +// s := Format('This is the text on the line %d. Hope the rendering will be fast', [i]); + if i < TFViewer(data).LineBuffer.Count + then s := {ANSIToUTF8(}TFViewer(data).LineBuffer[i] + else s := ''; + pango_layout_set_text(Layout, PChar(s), Length(PChar(s))); + gdk_draw_layout(PGdkDrawable(Awidget^.window), Awidget^.style^.fg_gc[GTK_WIDGET_STATE (Awidget)], 5, i * TFViewer(data).LineHeight, Layout); + end; + g_object_unref(Layout); + + +( * gdk_draw_arc(PGdkDrawable(Awidget^.window), + Awidget^.style^.fg_gc[GTK_WIDGET_STATE (Awidget)], + Integer(TRUE), + 0, 0, 500, 500, {Awidget^.allocation.width, Awidget^.allocation.height,} + 0, 64 * 360); +* ) + + // !!!!!!!!!!!! Toto oddelat (musi se volat asi po Application.ProcessMessages (se mne nechtelo s tim drbat tady)) + cursor := gdk_cursor_new(152); + gdk_window_set_cursor(AWidget^.window, cursor); + gdk_cursor_unref(cursor); + + Result := True; +end; +*) + +function TFViewer.LoadFile(FileName: string): boolean; +var Valid: boolean; + i: integer; +begin + Result := False; + try + LineBuffer := TStringList.Create; + LineBuffer.LoadFromFile(FileName); + + Valid := True; + for i := 0 to LineBuffer.Count - 1 do begin + Valid := Valid and g_utf8_validate(PChar(LineBuffer[i]), -1, nil); + if not Valid then Break; + end; + + if Valid then TextView.Lines.SetText(LineBuffer.Text) + else + for i := 0 to LineBuffer.Count - 1 do + TextView.Lines.InsertText(AnsiToUtf8(LineBuffer[i]) + #10); + + +{ LineHeight := 16; + NumLines := LineBuffer.Count; } + Caption := Format('TuxView [%s]', [ANSIToUTF8(FileName)]); +// FDrawingArea.SetSizeRequest(-1, NumLines * LineHeight); + Result := True; + except + Exit; + end; +end; + +(********************************************************************************************************************************) +procedure TViewerThread.Execute; +begin + gdk_threads_enter; +// DoIt; + AViewer.Show; +// AViewer.Run; + gdk_threads_leave; +end; + +constructor TViewerThread.Create(Parent: TComponent); +begin + AViewer := TFViewer.Create(Parent); + AViewer.AThread := Self; + FreeOnTerminate := True; + inherited Create(True); +end; + +destructor TViewerThread.Destroy; +begin +{ AViewer.Free; + inherited Destroy; } +end; + +function TViewerThread.LoadFile(FileName: string): boolean; +begin + Result := AViewer.LoadFile(FileName); +end; + +{procedure TViewerThread.DoIt; +begin + Application.MessageBox('ddd') +end; } + + +end. |
