Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- (*******************************************************************************
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- / Contributors(alphabetical order): /
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Dorin Duminica - http://www.delphigeist.com
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Change Log:
- ~~~~~~~~~~~~~~~~
- / v 1.1 /
- ~~~~~~~~~~~~~~~
- new:
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- - editor scroll from MiniMap
- - options class(to be extended)
- - published a few more properties
- fixes:
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- - fixed flickering on scroll
- - fixed line number calculation on click
- other:
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- - cleanups
- known issues:
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- - translation of "char" when clicking the map is
- not always correct needs rewrite
- ~~~~~~~~~~~~~~~
- / v 1.0 /
- ~~~~~~~~~~~~~~
- - initial release
- *******************************************************************************)
- unit SynMiniMap;
- interface
- uses
- SysUtils, Classes, Controls, Graphics,
- {$IFDEF FPC}
- LCLIntf, LCLType, SynEditPlugins, SynEditKeyCmds
- {$ELSE}
- Windows
- {$ENDIF}, SynEdit;
- const
- SYNMINIMAP_DEFAULT_HEIGHT = 400;
- SYNMINIMAP_DEFAULT_WIDTH = 200;
- SYNMINIMAP_DEFAULT_FONTFACTOR = 3;
- SYNMINIMAP_FONTFACTOR_MIN = 2;
- SYNMINIMAP_FONTFACTOR_MAX = 4;
- SYNMINIMAP_DEFAULT_OPTIONS_TABWIDTH = 4;
- type
- ///
- /// don't modify this, it will be extended to pass other information
- /// in the future without breaking backwards compatibility
- ///
- {$IFDEF FPC}
- TBufferCoord = record
- Char: integer;
- Line: integer;
- end;
- PPoint = ^TPoint;
- {$ENDIF}
- PSynMiniMapEventData = ^TSynMiniMapEventData;
- TSynMiniMapEventData = record
- Coord: TBufferCoord;
- Redraw: Boolean;
- end;
- const
- szSynMiniMapEventData = SizeOf(TSynMiniMapEventData);
- type
- ///
- /// colors for mini map
- ///
- TSynMiniMapColors = class(TPersistent)
- private
- FBackground: TColor;
- FHighlight: TColor;
- FPreviousLine: TColor;
- FPreviousLineText: TColor;
- FText: TColor;
- FTextHighlight: TColor;
- public
- constructor Create(AOwner: TComponent);
- published
- property Background: TColor read FBackground write FBackground;
- property Highlight: TColor read FHighlight write FHighlight;
- property PreviousLine: TColor read FPreviousLine write FPreviousLine;
- property PreviousLineText: TColor read FPreviousLineText write FPreviousLineText;
- property Text: TColor read FText write FText;
- property TextHighlight: TColor read FTextHighlight write FTextHighlight;
- end;
- ///
- /// various behavioral options
- ///
- TSynMinimapOptions = class(TPersistent)
- private
- FAllowScroll: Boolean;
- FReverseScroll: Boolean;
- FTabWidthOverride: Boolean;
- FTabWidth: Integer;
- public
- constructor Create(AOwner: TComponent);
- published
- ///
- /// scrolling editor using the MiniMap is possible only if AllowScroll
- ///
- property AllowScroll: Boolean read FAllowScroll write FAllowScroll;
- property ReverseScroll: Boolean read FReverseScroll write FReverseScroll;
- property TabWidthOverride: Boolean read FTabWidthOverride write FTabWidthOverride;
- property TabWidth: Integer read FTabWidth write FTabWidth;
- end;
- ///
- /// event fired under various conditions
- ///
- TSynMiniMapEvent = procedure (Sender: TObject; Data: PSynMiniMapEventData) of Object;
- ///
- /// forward declaration
- ///
- TSynMiniMap = class;
- ///
- /// this plugin helps hook a few important events
- ///
- TSynMiniMapEditorPlugin = class({$IFDEF FPC}TAbstractSynSingleHookPlugin{$ELSE}TSynEditPlugin{$ENDIF})
- private
- FSynMiniMap: TSynMiniMap;
- procedure RePaint;
- procedure UpdateLines(const FirstLine, Count: integer);
- protected
- {$IFDEF FPC}
- procedure OnCommand(Sender: TObject; AfterProcessing: boolean;
- var Handled: boolean; var Command: TSynEditorCommand;
- var aChar: TUTF8Char;
- Data: pointer; HandlerData: pointer); override;
- {$ELSE}
- procedure AfterPaint(ACanvas: TCanvas; const AClip: TRect;
- FirstLine: Integer; LastLine: Integer); override;
- procedure LinesDeleted(FirstLine: Integer; Count: Integer); override;
- procedure LinesInserted(FirstLine: Integer; Count: Integer); override;
- {$ENDIF}
- public
- constructor Create(ASynMiniMap: TSynMiniMap);
- end;
- ///
- /// the minimap itself
- ///
- TSynMiniMap = class(TCustomControl)
- protected
- procedure Resize; override;
- procedure Paint; override;
- procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X: Integer;
- Y: Integer); override;
- procedure MouseMove(Shift: TShiftState; X: Integer; Y: Integer); override;
- procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X: Integer;
- Y: Integer); override;
- procedure DoClick(const AX, AY: Integer); virtual;
- private
- FFullSizeBitmap: TBitmap;
- FOffsetBitmap: TBitmap;
- FEditor: TSynEdit;
- private
- FEditorHeight: Integer;
- FEditorWidth: Integer;
- FEditorRealWidth: Integer;
- FFirstLine: Integer;
- FLastLine: Integer;
- FMaxCharsPerLine: Word;
- FLineHeightInPixels: Integer;
- FPreviousLineIndex: Integer;
- FFontFactor: Single;
- FCharWidth: Integer;
- FTabWidth: Integer;
- FOptions: TSynMinimapOptions;
- ///
- /// mouse down & move => scroll
- /// mouse down + up => click
- ///
- FMouseDownPoint: TPoint;
- FMouseUpPoint: TPoint;
- FScrolling: Boolean;
- private
- FOnClick: TSynMiniMapEvent;
- private
- FColors: TSynMiniMapColors;
- FMiniMapPlugin: TSynMiniMapEditorPlugin;
- private
- function GetClickCoord: TBufferCoord;
- procedure ResetInternals;
- procedure ClearEventData(var AEventData: TSynMiniMapEventData);
- procedure Render; virtual;
- private
- function GetPixelFormat: TPixelFormat;
- procedure SetPixelFormat(const Value: TPixelFormat);
- procedure SetEditor(const Value: TSynEdit);
- procedure SetFontFactor(const Value: Single);
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- public
- function TranslatePoint(const APoint: PPoint): TBufferCoord;
- public
- property PreviousLineIndex: Integer read FPreviousLineIndex;
- property Scrolling: Boolean read FScrolling;
- published
- property Colors: TSynMiniMapColors read FColors write FColors;
- property Editor: TSynEdit read FEditor write SetEditor;
- property FontFactor: Single read FFontFactor write SetFontFactor;
- property Options: TSynMinimapOptions read FOptions write FOptions;
- property PixelFormat: TPixelFormat read GetPixelFormat write SetPixelFormat;
- published
- property OnClick: TSynMiniMapEvent read FOnClick write FOnClick;
- published
- property Align;
- property Constraints;
- property Height;
- property ShowHint;
- property Width;
- property OnDblClick;
- property OnResize;
- end;
- procedure Register;
- implementation
- uses
- Math
- ,Dialogs
- ;
- resourcestring
- SFontFactorMinMax = 'Font factor cannot be smaller than %.d or greater than %.d.';
- procedure Register;
- begin
- RegisterComponents('SynEdit', [TSynMiniMap]);
- end;
- {$IFNDEF FPC}
- procedure StretchDrawHalftone(Handle: THandle; const AX, AY, AWidth,
- AHeight: Integer; const ASource: TCanvas;
- const ASrcX, ASrcY, ASrcWidth, ASrcHeight: Integer);
- begin
- SetStretchBltMode(Handle, HALFTONE);
- StretchBlt(
- Handle,
- AX, AY,
- AWidth, AHeight,
- ASource.Handle,
- ASrcX, ASrcY,
- ASrcWidth, ASrcHeight,
- SRCCOPY
- );
- end;
- {$ENDIF}
- { TSynMiniMapColors }
- constructor TSynMiniMapColors.Create(AOwner: TComponent);
- begin
- inherited Create;
- ///
- /// set default values
- ///
- Background := clWhite;
- Highlight := $f4f4f4;
- PreviousLine := clNone;
- PreviousLineText := clNone;
- Text := clGray;
- TextHighlight := Text;
- end;
- { TSynMinimapOptions }
- constructor TSynMinimapOptions.Create(AOwner: TComponent);
- begin
- inherited Create;
- AllowScroll := False;
- ReverseScroll := False;
- TabWidthOverride := False;
- TabWidth := SYNMINIMAP_DEFAULT_OPTIONS_TABWIDTH;
- end;
- { TSynMiniMapEditorPlugin }
- constructor TSynMiniMapEditorPlugin.Create(ASynMiniMap: TSynMiniMap);
- begin
- {$IFDEF FPC}
- ShortCut := 1;
- {$ENDIF}
- FSynMiniMap := ASynMiniMap;
- inherited Create(ASynMiniMap.Editor);
- end;
- procedure TSynMiniMapEditorPlugin.Repaint;
- begin
- if assigned(FSynMiniMap) then FSynMiniMap.Render;
- end;
- procedure TSynMiniMapEditorPlugin.UpdateLines(const FirstLine, Count: integer);
- var
- LLineIndex: Integer;
- begin
- ///
- /// check if we need to decrement/increment the previous line index
- /// if current line index is 10 and the user deleted a few lines
- /// before that, we need to adjust FPreviousLineIndex
- ///
- LLineIndex := FirstLine -1;
- if assigned(FSynMiniMap) and (FSynMiniMap.PreviousLineIndex >= LLineIndex) then
- begin
- Inc(FSynMiniMap.FPreviousLineIndex, Count);
- Repaint;
- end;
- end;
- {$IFDEF FPC}
- procedure TSynMiniMapEditorPlugin.OnCommand(Sender: TObject; AfterProcessing: boolean;
- var Handled: boolean; var Command: TSynEditorCommand;
- var aChar: TUTF8Char;
- Data: pointer; HandlerData: pointer);
- begin
- if AfterProcessing then
- begin
- case Command of
- ecDeleteLine: Repaint;
- ecLineBreak, ecInsertLine: Repaint;
- end;
- end;
- end;
- {$ELSE}
- procedure TSynMiniMapEditorPlugin.AfterPaint(ACanvas: TCanvas;
- const AClip: TRect; FirstLine, LastLine: Integer);
- begin
- inherited;
- Repaint;
- end;
- procedure TSynMiniMapEditorPlugin.LinesDeleted(FirstLine, Count: Integer);
- begin
- inherited;
- UpdateLines(FirstLine, -Count);
- end;
- procedure TSynMiniMapEditorPlugin.LinesInserted(FirstLine, Count: Integer);
- begin
- inherited;
- UpdateLines(FirstLine, Count);
- end;
- {$ENDIF}
- { TSynMiniMap }
- procedure TSynMiniMap.ClearEventData(var AEventData: TSynMiniMapEventData);
- begin
- FillChar(AEventData, 0, szSynMiniMapEventData);
- end;
- constructor TSynMiniMap.Create(AOwner: TComponent);
- begin
- inherited;
- FFullSizeBitmap := TBitmap.Create;
- FOffsetBitmap := TBitmap.Create;
- FColors := TSynMiniMapColors.Create(Self);
- PixelFormat := pf32bit;
- Self.Height := SYNMINIMAP_DEFAULT_HEIGHT;
- Self.Width := SYNMINIMAP_DEFAULT_WIDTH;
- FMaxCharsPerLine := 100;
- FOptions := TSynMinimapOptions.Create(Self);
- FPreviousLineIndex := -1;
- FFontFactor := SYNMINIMAP_DEFAULT_FONTFACTOR;
- FScrolling := False;
- end;
- destructor TSynMiniMap.Destroy;
- begin
- FColors.Free;
- FFullSizeBitmap.Free;
- FOffsetBitmap.Free;
- FOptions.Free;
- inherited;
- end;
- procedure TSynMiniMap.DoClick(const AX, AY: Integer);
- var
- LEventData: TSynMiniMapEventData;
- LPoint: TPoint;
- begin
- ///
- /// OnClick has no value unless we have an editor assign
- ///
- if Assigned(FOnClick) and Assigned(FEditor) then begin
- ///
- /// save previous line index for drawing in Render
- ///
- FPreviousLineIndex := FEditor.CaretY -1;
- ///
- /// reset event data record
- ///
- ClearEventData(LEventData);
- ///
- /// set the Line and Char coordonates
- ///
- LPoint.X := AX;
- LPoint.Y := AY;
- LEventData.Coord := TranslatePoint(@LPoint);
- ///
- /// invoke assigned event
- ///
- FOnClick(Self, @LEventData);
- ///
- /// check if we were asked to redraw
- ///
- if LEventData.Redraw then
- Render;
- end;
- end;
- function TSynMiniMap.GetClickCoord: TBufferCoord;
- var
- LPoint: TPoint;
- begin
- ///
- /// grab the cursor coordonates
- ///
- LPoint := Point(0,0);
- GetCursorPos(LPoint);
- LPoint := Self.ScreenToClient(LPoint);
- Result := TranslatePoint(@LPoint);
- end;
- function TSynMiniMap.GetPixelFormat: TPixelFormat;
- begin
- ///
- /// return the current pixel format
- ///
- Result := FFullSizeBitmap.PixelFormat;
- end;
- procedure TSynMiniMap.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
- Y: Integer);
- begin
- inherited;
- FScrolling := ( mbLeft = Button ) and Options.AllowScroll;
- FMouseDownPoint.X := X;
- FMouseDownPoint.Y := Y;
- end;
- procedure TSynMiniMap.MouseMove(Shift: TShiftState; X, Y: Integer);
- var
- LDelta: Integer;
- LScrollDown: Boolean;
- begin
- inherited;
- if NOT Options.AllowScroll then
- Exit;
- if Scrolling and Assigned(Editor) then begin
- LDelta := FMouseDownPoint.Y - Y;
- LDelta := Trunc(LDelta / FFontFactor);
- LDelta := Abs(LDelta);
- LScrollDown := (Y > FMouseDownPoint.Y);
- if Options.ReverseScroll then
- LScrollDown := NOT LScrollDown;
- if LScrollDown then
- //if Y > FMouseDownPoint.Y then
- Editor.CaretY := Editor.CaretY + LDelta
- else
- Editor.CaretY := Editor.CaretY - LDelta;
- end;
- end;
- procedure TSynMiniMap.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
- Y: Integer);
- var
- LIsClick: Boolean;
- begin
- inherited;
- FScrolling := False;
- FMouseUpPoint.X := X;
- FMouseUpPoint.Y := Y;
- LIsClick := ( NOT Options.AllowScroll )
- or (( FMouseDownPoint.X = FMouseUpPoint.X)
- and (FMouseDownPoint.Y = FMouseUpPoint.Y ));
- if LIsClick then
- DoClick(X, Y);
- end;
- procedure TSynMiniMap.Paint;
- begin
- ///
- /// draw the buffered bitmap
- ///
- Canvas.Draw(0, 0, FOffsetBitmap);
- end;
- procedure TSynMiniMap.Render;
- var
- LLineHeight: Integer;
- LLineCount: Integer;
- LLineTop: Integer;
- LLineText: string;
- LMaxLineCount: Integer;
- LDrawHeight: Integer;
- LDrawWidth: Integer;
- LTopLineIndex: Integer;
- LFocusRect: TRect;
- LFocusTopIndex: Integer;
- LPreviousLine: Boolean;
- Index: Integer;
- function __get_line_xpos: Integer;
- ///
- /// this function is counting leading spaces and tabs
- /// could use improvements
- ///
- var
- cIndex: Integer;
- begin
- Result := 0;
- for cIndex := 1 to Length(LLineText) do
- case LLineText[cIndex] of
- #$9: Inc(Result, FTabWidth);
- ' ': Inc(Result, FCharWidth);
- else
- Break;
- end;
- end;
- begin
- if ( NOT Assigned(Editor) ) or ( csDestroying in ComponentState ) then
- Exit;
- ///
- /// this is where the magic happens
- /// what it does:
- /// - the MiniMap control has a limited height, we need to translate
- /// that height into a maximum number of lines we can display from
- /// the synedit control
- /// - create a "full size bitmap"
- /// - paint various misc stuff(highlight, previous line, etc.)
- /// - paint each line starting from X lines before current visible lines
- /// and Y lines after
- /// - scale down the "full size bitmap" and paint it on to the
- /// "offset bitmap"
- /// each time the "pain event" occures, the "offset bitmap" is used to
- /// draw on the MiniMap control
- ///
- ///
- /// grab the lines
- ///
- LLineCount := Editor.Lines.Count;
- ///
- /// store the first visible line index
- /// IMPORTANT:
- /// - synedit refers to lines as "real index" + 1
- ///
- LTopLineIndex := Editor.TopLine -1;
- ///
- /// grab the font size of full size bitmap
- ///
- LLineHeight := FFullSizeBitmap.Canvas.Font.Size;
- ///
- /// add a 2 pixel line spacing
- ///
- Inc(LLineHeight, 2);
- ///
- /// "shrink" the font to a much small dimension, each character will be
- /// FontFactor times smaller than the "real thing"
- ///
- FLineHeightInPixels := Trunc( LLineHeight / FFontFactor);
- ///
- /// calculate the maximum number of lines we can display
- /// IMPORTANT:
- /// - FLineHeightInPixels includes the "line spacing"
- ///
- LMaxLineCount := Self.Height div FLineHeightInPixels;
- ///
- /// calculate the smalles value of lines we will display
- /// if the lines in editor are more than we can display
- /// then we display the maximum possible, otherwise display as many
- /// as there are in the editor
- ///
- LLineCount := max(LLineCount, LMaxLineCount);
- ///
- /// setup the full size bitmap dimensions
- ///
- FFullSizeBitmap.Height := LLineCount * LLineHeight;
- ///
- /// setup the background color and fill it
- ///
- FFullSizeBitmap.Canvas.Brush.Color := Colors.Background;
- FFullSizeBitmap.Canvas.FillRect(Rect(0, 0, FFullSizeBitmap.Width, FFullSizeBitmap.Height));
- ///
- /// calculate the first and last lines that we will grab from editor
- /// and display in the MiniMap
- ///
- FFirstLine := LTopLineIndex - ( LMaxLineCount div 2 ) + (Editor.LinesInWindow div 2);
- FFirstLine := Max(FFirstLine, 0);
- FLastLine := Min(FFirstLine + LLineCount, Editor.Lines.Count -1);
- ///
- /// setup brush and pen
- ///
- FFullSizeBitmap.Canvas.Brush.Style := bsSolid;
- FFullSizeBitmap.Canvas.Brush.Color := Colors.Highlight;
- FFullSizeBitmap.Canvas.Pen.Style := psClear;
- ///
- /// highlight visible lines with provided color
- ///
- LFocusTopIndex := LTopLineIndex - FFirstLine;
- LFocusRect := Rect(
- 0,
- LFocusTopIndex * LLineHeight,
- FFullSizeBitmap.Width,
- ( LFocusTopIndex + Editor.LinesInWindow ) * LLineHeight
- );
- FFullSizeBitmap.Canvas.Rectangle(LFocusRect);
- ///
- /// check if we need to hightlight previous line
- /// previous line is saved when the user clicks on the MiniMap
- /// on MiniMap's OnClick event you can jump to the clicked line
- ///
- LPreviousLine := ( Colors.PreviousLine <> clNone ) and
- ( PreviousLineIndex >= FFirstLine ) and ( PreviousLineIndex <= FLastLine );
- if LPreviousLine then begin
- FFullSizeBitmap.Canvas.Brush.Color := Colors.PreviousLine;
- LFocusRect := Rect(
- 0,
- ( PreviousLineIndex - FFirstLine ) * LLineHeight,
- FFullSizeBitmap.Width,
- ( PreviousLineIndex - FFirstLine + 1) * LLineHeight);
- FFullSizeBitmap.Canvas.Rectangle(LFocusRect);
- end;
- ///
- /// set the brush style to clear, otherwise we get uggly background color
- /// for each line
- ///
- FFullSizeBitmap.Canvas.Brush.Style := bsClear;
- ///
- /// LLineTop holds the Y pixel value of the line
- ///
- LLineTop := 0;
- ///
- /// start drawing lines
- ///
- Index := FFirstLine;
- while Index <= FLastLine do begin
- ///
- /// grab current line text
- ///
- LLineText := Editor.Lines[Index];
- if ( Index = PreviousLineIndex ) and (Colors.PreviousLineText <> clNone) then
- ///
- /// color of the previous line if applies
- ///
- FFullSizeBitmap.Canvas.Font.Color := Colors.PreviousLineText
- else
- if ( Index >= LTopLineIndex ) and ( Index <= LTopLineIndex + Editor.LinesInWindow ) then
- ///
- /// font color of lines visible in the editor
- ///
- FFullSizeBitmap.Canvas.Font.Color := Colors.TextHighlight
- else
- ///
- /// normal text font color
- ///
- FFullSizeBitmap.Canvas.Font.Color := Colors.Text;
- ///
- /// draw the text
- /// at this point, the font size is the same as in the editor
- /// just the line spacing is smaller
- ///
- FFullSizeBitmap.Canvas.TextOut(__get_line_xpos, LLineTop, LLineText);
- ///
- /// increment the top pixel
- ///
- Inc(LLineTop, LLineHeight);
- ///
- /// increment the line
- ///
- Inc(Index);
- end;
- ///
- /// if the current number of lines in the editor is smaller than
- /// the maximum we can display, we need to fill the canvas with
- /// the provided background color
- ///
- FOffsetBitmap.Canvas.Brush.Color := Colors.Background;
- FOffsetBitmap.Canvas.FillRect(Rect(0, 0, Width, Height));
- ///
- /// and adjust the size of the "scaled down" version of full size bitmap
- ///
- LDrawHeight := Height;
- if FOffsetBitmap.Height > LLineCount * FLineHeightInPixels then
- LDrawheight := LLineCount * FLineHeightInPixels;
- LDrawWidth := Trunc(FFullSizeBitmap.Width / FFontFactor);
- {$IFDEF FPC}
- FOffsetBitmap.canvas.StretchDraw(Rect(0,0,LDrawWidth, LDrawHeight), FFullSizeBitmap);
- {$ELSE}
- StretchDrawHalftone(FOffsetBitmap.canvas.handle, 0, 0, LDrawWidth, LDrawheight,
- FFullSizeBitmap.Canvas, 0, 0, FFullSizeBitmap.Width, FFullSizeBitmap.Height);
- {$ENDIF}
- ///
- /// call paint to update the canvas
- ///
- Paint;
- end;
- procedure TSynMiniMap.ResetInternals;
- begin
- if NOT Assigned(Editor) then
- Exit;
- FEditorHeight := Editor.Height;
- FEditorWidth := Editor.Width;
- FEditorRealWidth := FEditorWidth - Editor.Gutter.Width;
- FFullSizeBitmap.Canvas.Brush.Style := bsSolid;
- FFullSizeBitmap.Canvas.Brush.Color := Colors.Background;
- FFullSizeBitmap.Canvas.Font.Height := Editor.Font.Height;
- FFullSizeBitmap.Canvas.Font.Size := Editor.Font.Size;
- FFullSizeBitmap.Canvas.Font.Name := Editor.Font.Name;
- FCharWidth := FFullSizeBitmap.Canvas.TextWidth('X');
- if Options.TabWidthOverride then
- FTabWidth := Options.TabWidth
- else
- FTabWidth := FCharWidth * Editor.TabWidth;
- FMaxCharsPerLine := Trunc(Self.Width / (FCharWidth / FFontFactor));
- FFullSizeBitmap.Width := FMaxCharsPerLine * FCharWidth;
- Self.Color := Editor.Color;
- Render;
- end;
- procedure TSynMiniMap.Resize;
- const
- CNO_EDITOR = '(no editor assigned)';
- var
- LTextHeight: Integer;
- LTextWidth: Integer;
- LTextX: Integer;
- LTextY: Integer;
- begin
- FOffsetBitmap.Height := Self.Height;
- FOffsetBitmap.Width := Self.Width;
- FOffsetBitmap.Canvas.Brush.Color := Colors.Background;
- FOffsetBitmap.Canvas.FillRect(Rect(0, 0, Width, Height));
- FOffsetBitmap.Canvas.Font.Color := Colors.Text;
- if csDesigning in ComponentState then begin
- LTextHeight := FOffsetBitmap.Canvas.TextHeight(CNO_EDITOR);
- LTextWidth := FOffsetBitmap.Canvas.TextWidth(CNO_EDITOR);
- LTextX := Width div 2 - LTextWidth div 2;
- LTextY := Height div 2 - LTextHeight div 2;
- FOffsetBitmap.Canvas.TextOut(LTextX, LTextY, CNO_EDITOR);
- end;
- ResetInternals;
- inherited Resize;
- end;
- procedure TSynMiniMap.SetFontFactor(const Value: Single);
- begin
- if ( Value < SYNMINIMAP_FONTFACTOR_MIN ) or
- ( Value > SYNMINIMAP_FONTFACTOR_MAX ) then begin
- MessageDlg(
- Format(SFontFactorMinMax, [SYNMINIMAP_FONTFACTOR_MIN,
- SYNMINIMAP_FONTFACTOR_MAX]),
- mtError, [mbOK], 0);
- Exit;
- end;
- FFontFactor := Value;
- Render;
- end;
- procedure TSynMiniMap.SetPixelFormat(const Value: TPixelFormat);
- begin
- ///
- /// set the pixel format on both bitmaps
- ///
- FFullSizeBitmap.PixelFormat := Value;
- FOffsetBitmap.PixelFormat := Value;
- end;
- function TSynMiniMap.TranslatePoint(const APoint: PPoint): TBufferCoord;
- var
- LChar: Integer;
- begin
- ///
- /// this method translates X and Y from control's surface into
- /// editor's Line and Char, mainly used in OnClick event
- ///
- if APoint^.X < 1 then
- LChar := 1
- else
- LChar := Trunc(APoint^.X / (FCharWidth / FFontFactor));
- if LChar > FMaxCharsPerLine then
- LChar := FMaxCharsPerLine;
- Result.Char := LChar;
- Result.Line := FFirstLine + APoint^.Y div FLineHeightInPixels +1;
- end;
- procedure TSynMiniMap.SetEditor(const Value: TSynEdit);
- begin
- FEditor := Value;
- ///
- /// create a plugin if we don't have one
- ///
- if Value <> NIL then
- FMiniMapPlugin := TSynMiniMapEditorPlugin.Create(Self);
- ResetInternals;
- end;
- initialization
- finalization
- end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement