mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-09 19:35:57 +02:00
gtk2 intf: fixed TTrackBar, added MergeSort for TFPList and TStrings
git-svn-id: trunk@9471 -
This commit is contained in:
parent
3bcc757e68
commit
486838638b
@ -138,7 +138,6 @@ begin
|
|||||||
FItemDataOffset := inherited GetCachedDataSize;
|
FItemDataOffset := inherited GetCachedDataSize;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TCustomCheckListBox.DoChange(var Msg);
|
procedure TCustomCheckListBox.DoChange(var Msg);
|
||||||
begin
|
begin
|
||||||
clickChecked;
|
clickChecked;
|
||||||
|
@ -45,12 +45,7 @@
|
|||||||
- range checking for min/max could raise an exception
|
- range checking for min/max could raise an exception
|
||||||
- use RecreateWnd when the orientation changes!
|
- use RecreateWnd when the orientation changes!
|
||||||
|
|
||||||
Bugs:
|
|
||||||
|
|
||||||
- When changing orientation after the Trackbar has been constructed
|
|
||||||
the GTK version will CRASH
|
|
||||||
}
|
}
|
||||||
{ASSERTIONS ON}
|
|
||||||
{------------------------------------------------------------------------------
|
{------------------------------------------------------------------------------
|
||||||
Method: TCustomTrackBar.Create
|
Method: TCustomTrackBar.Create
|
||||||
Params: AOwner: the owner of the class
|
Params: AOwner: the owner of the class
|
||||||
@ -75,7 +70,7 @@ begin
|
|||||||
FTickMarks:=tmBottomRight;
|
FTickMarks:=tmBottomRight;
|
||||||
FTickStyle:=tsAuto;
|
FTickStyle:=tsAuto;
|
||||||
TabStop := true;
|
TabStop := true;
|
||||||
SetInitialBounds(0,0,100,20);
|
SetInitialBounds(0,0,100,25);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{------------------------------------------------------------------------------
|
{------------------------------------------------------------------------------
|
||||||
@ -133,7 +128,7 @@ end;
|
|||||||
Method: TCustomTrackBar.SetParams
|
Method: TCustomTrackBar.SetParams
|
||||||
Params: APosition : new position
|
Params: APosition : new position
|
||||||
AMin : new minimum
|
AMin : new minimum
|
||||||
AMax : new maximum
|
AMax : new maximum
|
||||||
Returns: Nothing
|
Returns: Nothing
|
||||||
|
|
||||||
Set new parameters for the trackbar.
|
Set new parameters for the trackbar.
|
||||||
|
@ -3632,6 +3632,7 @@ begin
|
|||||||
|
|
||||||
LM_DESTROY :
|
LM_DESTROY :
|
||||||
begin
|
begin
|
||||||
|
//DebugLn(['TGtkWidgetSet.SetCallback ',DbgSName(ALCLObject)]);
|
||||||
ConnectSenderSignal(gObject, 'destroy', @gtkdestroyCB);
|
ConnectSenderSignal(gObject, 'destroy', @gtkdestroyCB);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -4640,7 +4640,7 @@ end;
|
|||||||
Returns: Nothing
|
Returns: Nothing
|
||||||
|
|
||||||
Connects a gtk signal handler.
|
Connects a gtk signal handler.
|
||||||
This is wrappers to get around gtk casting
|
This is a wrapper to get around gtk casting
|
||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
procedure SignalConnect(const AWidget: PGTKWidget; const ASignal: PChar;
|
procedure SignalConnect(const AWidget: PGTKWidget; const ASignal: PChar;
|
||||||
const AProc: Pointer; const AInfo: PWidgetInfo);
|
const AProc: Pointer; const AInfo: PWidgetInfo);
|
||||||
@ -4657,7 +4657,7 @@ end;
|
|||||||
Returns: Nothing
|
Returns: Nothing
|
||||||
|
|
||||||
Connects a gtk signal after handler.
|
Connects a gtk signal after handler.
|
||||||
This is wrappers to get around gtk casting
|
This is a wrapper to get around gtk casting
|
||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
procedure SignalConnectAfter(const AWidget:PGTKWidget; const ASignal: PChar;
|
procedure SignalConnectAfter(const AWidget:PGTKWidget; const ASignal: PChar;
|
||||||
const AProc: Pointer; const AInfo: PWidgetInfo);
|
const AProc: Pointer; const AInfo: PWidgetInfo);
|
||||||
@ -4775,8 +4775,7 @@ begin
|
|||||||
and (not (csfDesignOnly in ASFlags))
|
and (not (csfDesignOnly in ASFlags))
|
||||||
then begin
|
then begin
|
||||||
OldDesignMask := GetDesignSignalMask(PGtkWidget(AnObject));
|
OldDesignMask := GetDesignSignalMask(PGtkWidget(AnObject));
|
||||||
NewDesignMask :=
|
NewDesignMask :=OldDesignMask and not DesignSignalMasks[DesignSignalType];
|
||||||
OldDesignMask and not DesignSignalMasks[DesignSignalType];
|
|
||||||
if OldDesignMask <> NewDesignMask
|
if OldDesignMask <> NewDesignMask
|
||||||
then SetDesignSignalMask(PGtkWidget(AnObject),NewDesignMask);
|
then SetDesignSignalMask(PGtkWidget(AnObject),NewDesignMask);
|
||||||
end;
|
end;
|
||||||
|
@ -619,7 +619,7 @@ function GetDesignOnlySignalFlag(Widget: PGtkWidget;
|
|||||||
// new signal procs, these will obsolete the old ones
|
// new signal procs, these will obsolete the old ones
|
||||||
// new signalshandlers are attached locally in the new WSxxx classes
|
// new signalshandlers are attached locally in the new WSxxx classes
|
||||||
// they also have PWidgetInfo as data (and not the TControl)
|
// they also have PWidgetInfo as data (and not the TControl)
|
||||||
// singnals are now also handled dedicated and locally, so no case statements
|
// signals are now also handled dedicated and locally, so no case statements
|
||||||
// anymore in signal handlers
|
// anymore in signal handlers
|
||||||
procedure SignalConnect(const AWidget: PGTKWidget; const ASignal: PChar;
|
procedure SignalConnect(const AWidget: PGTKWidget; const ASignal: PChar;
|
||||||
const AProc: Pointer; const AInfo: PWidgetInfo);
|
const AProc: Pointer; const AInfo: PWidgetInfo);
|
||||||
|
@ -337,17 +337,17 @@ end;
|
|||||||
class procedure TGtkWSTrackBar.ApplyChanges(const ATrackBar: TCustomTrackBar);
|
class procedure TGtkWSTrackBar.ApplyChanges(const ATrackBar: TCustomTrackBar);
|
||||||
var
|
var
|
||||||
wHandle: HWND;
|
wHandle: HWND;
|
||||||
Widget: PGtkWidget;
|
Adjustment: PGtkAdjustment;
|
||||||
begin
|
begin
|
||||||
with ATrackBar do
|
with ATrackBar do
|
||||||
begin
|
begin
|
||||||
wHandle := Handle;
|
wHandle := Handle;
|
||||||
Widget := GTK_WIDGET(gtk_range_get_adjustment (GTK_RANGE(Pointer(wHandle))));
|
Adjustment := gtk_range_get_adjustment (GTK_RANGE(Pointer(wHandle)));
|
||||||
GTK_ADJUSTMENT(Widget)^.lower := Min;
|
Adjustment^.lower := Min;
|
||||||
GTK_ADJUSTMENT(Widget)^.Upper := Max;
|
Adjustment^.Upper := Max;
|
||||||
GTK_ADJUSTMENT(Widget)^.Value := Position;
|
Adjustment^.Value := Position;
|
||||||
GTK_ADJUSTMENT(Widget)^.step_increment := LineSize;
|
Adjustment^.step_increment := LineSize;
|
||||||
GTK_ADJUSTMENT(Widget)^.page_increment := PageSize;
|
Adjustment^.page_increment := PageSize;
|
||||||
{ now do some of the more sophisticated features }
|
{ now do some of the more sophisticated features }
|
||||||
{ Hint: For some unknown reason we have to disable the draw_value first,
|
{ Hint: For some unknown reason we have to disable the draw_value first,
|
||||||
otherwise it's set always to true }
|
otherwise it's set always to true }
|
||||||
@ -363,7 +363,7 @@ begin
|
|||||||
trBottom: gtk_scale_set_value_pos (GTK_SCALE (Pointer(wHandle)), GTK_POS_BOTTOM);
|
trBottom: gtk_scale_set_value_pos (GTK_SCALE (Pointer(wHandle)), GTK_POS_BOTTOM);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
//Not here (Delphi compatibility): gtk_signal_emit_by_name (GTK_Object (Widget), 'value_changed');
|
//Not here (Delphi compatibility): gtk_signal_emit_by_name (GTK_Object (Adjustment), 'value_changed');
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -328,7 +328,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class procedure TGtkWSWinControl.SetCallbacks(const AGTKObject: PGTKObject; const AComponent: TComponent);
|
class procedure TGtkWSWinControl.SetCallbacks(const AGTKObject: PGTKObject;
|
||||||
|
const AComponent: TComponent);
|
||||||
begin
|
begin
|
||||||
GtkWidgetSet.SetCallback(LM_SHOWWINDOW, AGTKObject, AComponent);
|
GtkWidgetSet.SetCallback(LM_SHOWWINDOW, AGTKObject, AComponent);
|
||||||
GtkWidgetSet.SetCallback(LM_DESTROY, AGTKObject, AComponent);
|
GtkWidgetSet.SetCallback(LM_DESTROY, AGTKObject, AComponent);
|
||||||
@ -836,9 +837,11 @@ begin
|
|||||||
// SetCallbacks isn't called here, it should be done in the 'derived' class
|
// SetCallbacks isn't called here, it should be done in the 'derived' class
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class procedure TGtkWSBaseScrollingWinControl.SetCallbacks(const AWidget: PGtkWidget; const AWidgetInfo: PWidgetInfo);
|
class procedure TGtkWSBaseScrollingWinControl.SetCallbacks(
|
||||||
|
const AWidget: PGtkWidget; const AWidgetInfo: PWidgetInfo);
|
||||||
begin
|
begin
|
||||||
TGtkWSWinControl.SetCallbacks(PGtkObject(AWidget), TComponent(AWidgetInfo^.LCLObject));
|
TGtkWSWinControl.SetCallbacks(PGtkObject(AWidget),
|
||||||
|
TComponent(AWidgetInfo^.LCLObject));
|
||||||
|
|
||||||
SignalConnect(
|
SignalConnect(
|
||||||
PGtkWidget(gtk_scrolled_window_get_hadjustment(PGTKScrolledWindow(AWidget))),
|
PGtkWidget(gtk_scrolled_window_get_hadjustment(PGTKScrolledWindow(AWidget))),
|
||||||
|
@ -104,7 +104,8 @@ type
|
|||||||
procedure SetSorted(Val : boolean); virtual;
|
procedure SetSorted(Val : boolean); virtual;
|
||||||
procedure UpdateItemCache;
|
procedure UpdateItemCache;
|
||||||
public
|
public
|
||||||
constructor Create(ListStore : PGtkListStore; ColumnIndex : Integer; TheOwner: TWinControl);
|
constructor Create(ListStore : PGtkListStore;
|
||||||
|
ColumnIndex : Integer; TheOwner: TWinControl);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
function Add(const S: string): Integer; override;
|
function Add(const S: string): Integer; override;
|
||||||
procedure Assign(Source : TPersistent); override;
|
procedure Assign(Source : TPersistent); override;
|
||||||
@ -193,7 +194,8 @@ const
|
|||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
------------------------------------------------------------------------------}
|
------------------------------------------------------------------------------}
|
||||||
constructor TGtkListStoreStringList.Create(ListStore : PGtkListStore; ColumnIndex : Integer; TheOwner: TWinControl);
|
constructor TGtkListStoreStringList.Create(ListStore : PGtkListStore;
|
||||||
|
ColumnIndex : Integer; TheOwner: TWinControl);
|
||||||
begin
|
begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
if ListStore = nil then RaiseException(
|
if ListStore = nil then RaiseException(
|
||||||
@ -232,10 +234,19 @@ end;
|
|||||||
|
|
||||||
------------------------------------------------------------------------------}
|
------------------------------------------------------------------------------}
|
||||||
procedure TGtkListStoreStringList.SetSorted(Val : boolean);
|
procedure TGtkListStoreStringList.SetSorted(Val : boolean);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
if Val <> FSorted then begin
|
if Val <> FSorted then begin
|
||||||
|
if Val then begin
|
||||||
|
for i:=0 to Count-2 do begin
|
||||||
|
if AnsiCompareText(Strings[i],Strings[i+1])<0 then begin
|
||||||
|
Sort;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
FSorted:= Val;
|
FSorted:= Val;
|
||||||
if FSorted then Sort;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -284,16 +295,17 @@ end;
|
|||||||
procedure TGtkListStoreStringList.Sort;
|
procedure TGtkListStoreStringList.Sort;
|
||||||
var
|
var
|
||||||
sl: TStringList;
|
sl: TStringList;
|
||||||
|
OldSorted: Boolean;
|
||||||
begin
|
begin
|
||||||
BeginUpdate;
|
BeginUpdate;
|
||||||
// sort internally (sorting in the widget would be slow and unpretty ;)
|
// sort internally (sorting in the widget would be slow and unpretty ;)
|
||||||
sl:=TStringList.Create;
|
sl:=TStringList.Create;
|
||||||
sl.Assign(Self);
|
sl.Assign(Self);
|
||||||
sl.Sort; // currently this is quicksort ->
|
MergeSort(sl,@AnsiCompareText);
|
||||||
// Disadvantages: - worst case on sorted list
|
OldSorted:=Sorted;
|
||||||
// - not keeping order
|
FSorted:=false;
|
||||||
// ToDo: replace by mergesort and add customsort
|
|
||||||
Assign(sl);
|
Assign(sl);
|
||||||
|
FSorted:=OldSorted;
|
||||||
sl.Free;
|
sl.Free;
|
||||||
EndUpdate;
|
EndUpdate;
|
||||||
end;
|
end;
|
||||||
@ -301,7 +313,6 @@ end;
|
|||||||
function TGtkListStoreStringList.IsEqual(List: TStrings): boolean;
|
function TGtkListStoreStringList.IsEqual(List: TStrings): boolean;
|
||||||
var
|
var
|
||||||
i, Cnt: integer;
|
i, Cnt: integer;
|
||||||
CmpList: TStringList;
|
|
||||||
begin
|
begin
|
||||||
if List=Self then begin
|
if List=Self then begin
|
||||||
Result:=true;
|
Result:=true;
|
||||||
@ -312,30 +323,20 @@ begin
|
|||||||
BeginUpdate;
|
BeginUpdate;
|
||||||
Cnt:=Count;
|
Cnt:=Count;
|
||||||
if (Cnt<>List.Count) then exit;
|
if (Cnt<>List.Count) then exit;
|
||||||
CmpList:=TStringList.Create;
|
for i:=0 to Cnt-1 do
|
||||||
try
|
if (Strings[i]<>List[i]) or (Objects[i]<>List.Objects[i]) then exit;
|
||||||
CmpList.Assign(List);
|
|
||||||
CmpList.Sorted:=FSorted;
|
|
||||||
for i:=0 to Cnt-1 do begin
|
|
||||||
if (Strings[i]<>CmpList[i]) or (Objects[i]<>CmpList.Objects[i]) then exit;
|
|
||||||
end;
|
|
||||||
finally
|
|
||||||
CmpList.Free;
|
|
||||||
end;
|
|
||||||
Result:=true;
|
Result:=true;
|
||||||
EndUpdate;
|
EndUpdate;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TGtkListStoreStringList.BeginUpdate;
|
procedure TGtkListStoreStringList.BeginUpdate;
|
||||||
begin
|
begin
|
||||||
if FUpdateCount=0 then Include(FStates,glsItemCacheNeedsUpdate);
|
|
||||||
inc(FUpdateCount);
|
inc(FUpdateCount);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TGtkListStoreStringList.EndUpdate;
|
procedure TGtkListStoreStringList.EndUpdate;
|
||||||
begin
|
begin
|
||||||
dec(FUpdateCount);
|
dec(FUpdateCount);
|
||||||
if FUpdateCount=0 then Include(FStates,glsItemCacheNeedsUpdate);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{------------------------------------------------------------------------------
|
{------------------------------------------------------------------------------
|
||||||
@ -347,22 +348,33 @@ end;
|
|||||||
procedure TGtkListStoreStringList.Assign(Source : TPersistent);
|
procedure TGtkListStoreStringList.Assign(Source : TPersistent);
|
||||||
var
|
var
|
||||||
i, Cnt: integer;
|
i, Cnt: integer;
|
||||||
|
CmpList: TStrings;
|
||||||
|
OldSorted: Boolean;
|
||||||
begin
|
begin
|
||||||
if (Source=Self) or (Source=nil) then exit;
|
if (Source=Self) or (Source=nil) then exit;
|
||||||
if ((Source is TGtkListStoreStringList)
|
if ((Source is TGtkListStoreStringList)
|
||||||
and (TGtkListStoreStringList(Source).FGtkListStore=FGtkListStore))
|
and (TGtkListStoreStringList(Source).FGtkListStore=FGtkListStore))
|
||||||
then
|
then
|
||||||
RaiseException('TGtkListStoreStringList.Assign: There 2 lists with the same FGtkListStore');
|
RaiseException('TGtkListStoreStringList.Assign: There are 2 lists with the same FGtkListStore');
|
||||||
BeginUpdate;
|
BeginUpdate;
|
||||||
|
OldSorted:=Sorted;
|
||||||
|
CmpList:=nil;
|
||||||
try
|
try
|
||||||
if Source is TStrings then begin
|
if Source is TStrings then begin
|
||||||
// clearing and resetting can change other properties of the widget,
|
// clearing and resetting can change other properties of the widget,
|
||||||
// => don't change if the content is already the same
|
// => don't change if the content is already the same
|
||||||
if IsEqual(TStrings(Source)) then exit;
|
if Sorted then begin
|
||||||
|
CmpList:=TStringList.Create;
|
||||||
|
CmpList.Assign(TStrings(Source));
|
||||||
|
MergeSort(TStringList(CmpList),@AnsiCompareText);
|
||||||
|
end else
|
||||||
|
CmpList:=TStrings(Source);
|
||||||
|
if IsEqual(CmpList) then exit;
|
||||||
Clear;
|
Clear;
|
||||||
|
FSorted:=false;
|
||||||
Cnt:=TStrings(Source).Count;
|
Cnt:=TStrings(Source).Count;
|
||||||
for i:=0 to Cnt - 1 do begin
|
for i:=0 to Cnt - 1 do begin
|
||||||
AddObject(TStrings(Source)[i],TStrings(Source).Objects[i]);
|
AddObject(CmpList[i],CmpList.Objects[i]);
|
||||||
end;
|
end;
|
||||||
// ToDo: restore other settings
|
// ToDo: restore other settings
|
||||||
|
|
||||||
@ -370,6 +382,8 @@ begin
|
|||||||
end else
|
end else
|
||||||
inherited Assign(Source);
|
inherited Assign(Source);
|
||||||
finally
|
finally
|
||||||
|
fSorted:=OldSorted;
|
||||||
|
if CmpList<>Source then CmpList.Free;
|
||||||
EndUpdate;
|
EndUpdate;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -392,7 +406,8 @@ begin
|
|||||||
ListItem:=FCachedItems[Index];
|
ListItem:=FCachedItems[Index];
|
||||||
|
|
||||||
Item := nil;
|
Item := nil;
|
||||||
gtk_tree_model_get(GTK_TREE_MODEL(FGtkListStore), @ListItem, [FColumnIndex, @Item, -1]);
|
gtk_tree_model_get(GTK_TREE_MODEL(FGtkListStore), @ListItem,
|
||||||
|
[FColumnIndex, @Item, -1]);
|
||||||
if (Item <> nil) then begin
|
if (Item <> nil) then begin
|
||||||
Result:= StrPas(Item);
|
Result:= StrPas(Item);
|
||||||
g_free(Item);
|
g_free(Item);
|
||||||
@ -454,7 +469,7 @@ end;
|
|||||||
procedure TGtkListStoreStringList.Clear;
|
procedure TGtkListStoreStringList.Clear;
|
||||||
begin
|
begin
|
||||||
Include(FStates,glsItemCacheNeedsUpdate);
|
Include(FStates,glsItemCacheNeedsUpdate);
|
||||||
gtk_list_store_clear(FGtkListStore)
|
gtk_list_store_clear(FGtkListStore);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{------------------------------------------------------------------------------
|
{------------------------------------------------------------------------------
|
||||||
@ -542,7 +557,6 @@ begin
|
|||||||
gtk_list_store_set(FGtkListStore, @li, [FColumnIndex, PChar(S), -1]);
|
gtk_list_store_set(FGtkListStore, @li, [FColumnIndex, PChar(S), -1]);
|
||||||
|
|
||||||
Include(FStates,glsItemCacheNeedsUpdate);
|
Include(FStates,glsItemCacheNeedsUpdate);
|
||||||
|
|
||||||
finally
|
finally
|
||||||
EndUpdate;
|
EndUpdate;
|
||||||
end;
|
end;
|
||||||
|
@ -79,7 +79,7 @@ begin
|
|||||||
aWidget := WidgetInfo^.CoreWidget;
|
aWidget := WidgetInfo^.CoreWidget;
|
||||||
aTreeModel := gtk_tree_view_get_model (GTK_TREE_VIEW(aWidget));
|
aTreeModel := gtk_tree_view_get_model (GTK_TREE_VIEW(aWidget));
|
||||||
if (gtk_tree_model_get_iter_from_string (aTreeModel, @aTreeIter, arg1)) then begin
|
if (gtk_tree_model_get_iter_from_string (aTreeModel, @aTreeIter, arg1)) then begin
|
||||||
aTreeIter.stamp := GTK_LIST_STORE (aTreeModel)^.stamp; //strange hack
|
// aTreeIter.stamp := GTK_LIST_STORE (aTreeModel)^.stamp; //strange hack
|
||||||
value := g_new0(SizeOf(TgValue), 1);
|
value := g_new0(SizeOf(TgValue), 1);
|
||||||
gtk_tree_model_get_value(aTreeModel, @aTreeIter, 0, value);
|
gtk_tree_model_get_value(aTreeModel, @aTreeIter, 0, value);
|
||||||
|
|
||||||
@ -103,7 +103,7 @@ var
|
|||||||
begin
|
begin
|
||||||
aTreeModel := gtk_tree_view_get_model (treeview);
|
aTreeModel := gtk_tree_view_get_model (treeview);
|
||||||
if (gtk_tree_model_get_iter (aTreeModel, @aTreeIter, arg1)) then begin
|
if (gtk_tree_model_get_iter (aTreeModel, @aTreeIter, arg1)) then begin
|
||||||
aTreeIter.stamp := GTK_LIST_STORE (aTreeModel)^.stamp; //strange hack
|
// aTreeIter.stamp := GTK_LIST_STORE (aTreeModel)^.stamp; //strange hack
|
||||||
value := g_new0(SizeOf(TgValue), 1);
|
value := g_new0(SizeOf(TgValue), 1);
|
||||||
gtk_tree_model_get_value(aTreeModel, @aTreeIter, 0, value);
|
gtk_tree_model_get_value(aTreeModel, @aTreeIter, 0, value);
|
||||||
|
|
||||||
@ -121,7 +121,6 @@ class procedure TGtk2WSCustomCheckListBox.SetCallbacks(const AGtkWidget: PGtkWid
|
|||||||
// Selection: PGtkTreeSelection;
|
// Selection: PGtkTreeSelection;
|
||||||
begin
|
begin
|
||||||
TGtkWSBaseScrollingWinControl.SetCallbacks(AGtkWidget,AWidgetInfo);
|
TGtkWSBaseScrollingWinControl.SetCallbacks(AGtkWidget,AWidgetInfo);
|
||||||
TGtkWSWinControl.SetCallbacks(PGtkObject(AWidgetInfo^.CoreWidget), TComponent(AWidgetInfo^.LCLObject));
|
|
||||||
|
|
||||||
{Selection :=} gtk_tree_view_get_selection(PGtkTreeView(AWidgetInfo^.CoreWidget));
|
{Selection :=} gtk_tree_view_get_selection(PGtkTreeView(AWidgetInfo^.CoreWidget));
|
||||||
//SignalConnect(PGtkWidget(Selection), 'changed', @Gtk2WS_ListBoxChange, AWidgetInfo);
|
//SignalConnect(PGtkWidget(Selection), 'changed', @Gtk2WS_ListBoxChange, AWidgetInfo);
|
||||||
@ -161,10 +160,10 @@ begin
|
|||||||
gtk_list_store_set(ListStore, @Iter, [0, AChecked, -1]);
|
gtk_list_store_set(ListStore, @Iter, [0, AChecked, -1]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TGtk2WSCustomCheckListBox.CreateHandle(const AWinControl: TWinControl;
|
class function TGtk2WSCustomCheckListBox.CreateHandle(
|
||||||
const AParams: TCreateParams): TLCLIntfHandle;
|
const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle;
|
||||||
var
|
var
|
||||||
TempWidget: PGtkWidget;
|
TreeViewWidget: PGtkWidget;
|
||||||
p: PGtkWidget; // ptr to the newly created GtkWidget
|
p: PGtkWidget; // ptr to the newly created GtkWidget
|
||||||
liststore : PGtkListStore;
|
liststore : PGtkListStore;
|
||||||
Selection: PGtkTreeSelection;
|
Selection: PGtkTreeSelection;
|
||||||
@ -172,7 +171,6 @@ var
|
|||||||
column : PGtkTreeViewColumn;
|
column : PGtkTreeViewColumn;
|
||||||
WidgetInfo: PWidgetInfo;
|
WidgetInfo: PWidgetInfo;
|
||||||
begin
|
begin
|
||||||
|
|
||||||
Result := TGtkWSBaseScrollingWinControl.CreateHandle(AWinControl,AParams);
|
Result := TGtkWSBaseScrollingWinControl.CreateHandle(AWinControl,AParams);
|
||||||
p:= PGtkWidget(Result);
|
p:= PGtkWidget(Result);
|
||||||
|
|
||||||
@ -187,39 +185,41 @@ begin
|
|||||||
gtk_scrolled_window_set_shadow_type(PGtkScrolledWindow(p),GTK_SHADOW_IN);
|
gtk_scrolled_window_set_shadow_type(PGtkScrolledWindow(p),GTK_SHADOW_IN);
|
||||||
gtk_widget_show(p);
|
gtk_widget_show(p);
|
||||||
|
|
||||||
liststore := gtk_list_store_new (3, [G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_POINTER, nil]);
|
liststore := gtk_list_store_new (3,
|
||||||
|
[G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_POINTER, nil]);
|
||||||
TempWidget:= gtk_tree_view_new_with_model (GTK_TREE_MODEL (liststore));
|
TreeViewWidget:= gtk_tree_view_new_with_model (GTK_TREE_MODEL(liststore));
|
||||||
g_object_unref (G_OBJECT (liststore));
|
g_object_unref (G_OBJECT (liststore));
|
||||||
|
|
||||||
// Check Column
|
// Check Column
|
||||||
renderer := gtk_cell_renderer_toggle_new();
|
renderer := gtk_cell_renderer_toggle_new();
|
||||||
column := gtk_tree_view_column_new_with_attributes('', renderer, ['active', 0, nil]);
|
column := gtk_tree_view_column_new_with_attributes(
|
||||||
|
'CHECKBTNS', renderer, ['active', 0, nil]);
|
||||||
gtk_cell_renderer_toggle_set_active(GTK_CELL_RENDERER_TOGGLE(renderer), True);
|
gtk_cell_renderer_toggle_set_active(GTK_CELL_RENDERER_TOGGLE(renderer), True);
|
||||||
gtk_tree_view_append_column (GTK_TREE_VIEW (TempWidget), column);
|
gtk_tree_view_append_column (GTK_TREE_VIEW (TreeViewWidget), column);
|
||||||
gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
|
gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
|
||||||
|
|
||||||
SignalConnect(PGtkWidget(renderer), 'toggled', @Gtk2WS_CheckListBoxToggle, WidgetInfo);
|
SignalConnect(PGtkWidget(renderer), 'toggled', @Gtk2WS_CheckListBoxToggle, WidgetInfo);
|
||||||
SignalConnect(PGtkWidget(renderer), 'row_activated', @Gtk2WS_CheckListBoxRowActivate, WidgetInfo);
|
SignalConnect(TreeViewWidget, 'row_activated', @Gtk2WS_CheckListBoxRowActivate, WidgetInfo);
|
||||||
|
|
||||||
//g_signal_connect (renderer, 'toggled', G_CALLBACK (@gtk_clb_toggle), AWinControl);
|
//g_signal_connect (renderer, 'toggled', G_CALLBACK (@gtk_clb_toggle), AWinControl);
|
||||||
//g_signal_connect (TempWidget, 'row_activated', G_CALLBACK (@gtk_clb_toggle_row_activated), AWinControl);
|
//g_signal_connect (TreeViewWidget, 'row_activated', G_CALLBACK (@gtk_clb_toggle_row_activated), AWinControl);
|
||||||
|
|
||||||
// Text Column
|
// Text Column
|
||||||
renderer := gtk_cell_renderer_text_new();
|
renderer := gtk_cell_renderer_text_new();
|
||||||
column := gtk_tree_view_column_new_with_attributes ('LISTITEMS', renderer, ['text', 1, nil]);
|
column := gtk_tree_view_column_new_with_attributes (
|
||||||
gtk_tree_view_append_column (GTK_TREE_VIEW (TempWidget), column);
|
'LISTITEMS', renderer, ['text', 1, nil]);
|
||||||
|
gtk_tree_view_append_column (GTK_TREE_VIEW (TreeViewWidget), column);
|
||||||
gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
|
gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
|
||||||
|
|
||||||
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW (TempWidget), False);
|
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW (TreeViewWidget), False);
|
||||||
|
|
||||||
gtk_container_add(GTK_CONTAINER(p), TempWidget);
|
gtk_container_add(GTK_CONTAINER(p), TreeViewWidget);
|
||||||
gtk_widget_show(TempWidget);
|
gtk_widget_show(TreeViewWidget);
|
||||||
|
|
||||||
SetMainWidget(p, TempWidget);
|
SetMainWidget(p, TreeViewWidget);
|
||||||
GetWidgetInfo(p, True)^.CoreWidget := TempWidget;
|
GetWidgetInfo(p, True)^.CoreWidget := TreeViewWidget;
|
||||||
|
|
||||||
Selection := gtk_tree_view_get_selection(PGtkTreeView(TempWidget));
|
Selection := gtk_tree_view_get_selection(PGtkTreeView(TreeViewWidget));
|
||||||
|
|
||||||
case TCustomCheckListBox(AWinControl).MultiSelect of
|
case TCustomCheckListBox(AWinControl).MultiSelect of
|
||||||
True : gtk_tree_selection_set_mode(Selection, GTK_SELECTION_MULTIPLE);
|
True : gtk_tree_selection_set_mode(Selection, GTK_SELECTION_MULTIPLE);
|
||||||
@ -236,6 +236,6 @@ initialization
|
|||||||
// To improve speed, register only classes
|
// To improve speed, register only classes
|
||||||
// which actually implement something
|
// which actually implement something
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
RegisterWSComponent(TCheckListBox, TGtk2WSCustomCheckListBox);
|
RegisterWSComponent(TCustomCheckListBox, TGtk2WSCustomCheckListBox);
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
end.
|
end.
|
||||||
|
@ -95,11 +95,11 @@ type
|
|||||||
class function GetStrings(const ACustomListBox: TCustomListBox): TStrings; override;
|
class function GetStrings(const ACustomListBox: TCustomListBox): TStrings; override;
|
||||||
class function GetItemIndex(const ACustomListBox: TCustomListBox): integer; override;
|
class function GetItemIndex(const ACustomListBox: TCustomListBox): integer; override;
|
||||||
class function GetTopIndex(const ACustomListBox: TCustomListBox): integer; override;
|
class function GetTopIndex(const ACustomListBox: TCustomListBox): integer; override;
|
||||||
class procedure SelectItem(const ACustomListBox: TCustomListBox; AIndex: integer; ASelected: boolean); override;
|
class procedure SelectItem(const ACustomListBox: TCustomListBox; AnIndex: integer; ASelected: boolean); override;
|
||||||
class procedure SetBorder(const ACustomListBox: TCustomListBox); override;
|
class procedure SetBorder(const ACustomListBox: TCustomListBox); override;
|
||||||
class procedure SetItemIndex(const ACustomListBox: TCustomListBox; const AIndex: integer); override;
|
class procedure SetItemIndex(const ACustomListBox: TCustomListBox; const AIndex: integer); override;
|
||||||
class procedure SetSelectionMode(const ACustomListBox: TCustomListBox; const AExtendedSelect,
|
class procedure SetSelectionMode(const ACustomListBox: TCustomListBox; const AExtendedSelect,
|
||||||
AMultiSelect: boolean); override;
|
AMultiSelect: boolean); override;
|
||||||
class procedure SetSorted(const ACustomListBox: TCustomListBox; AList: TStrings; ASorted: boolean); override;
|
class procedure SetSorted(const ACustomListBox: TCustomListBox; AList: TStrings; ASorted: boolean); override;
|
||||||
class procedure SetTopIndex(const ACustomListBox: TCustomListBox; const NewTopIndex: integer); override;
|
class procedure SetTopIndex(const ACustomListBox: TCustomListBox; const NewTopIndex: integer); override;
|
||||||
class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override;
|
class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override;
|
||||||
@ -256,8 +256,8 @@ begin
|
|||||||
DeliverMessage(WidgetInfo^.LCLObject, Mess);
|
DeliverMessage(WidgetInfo^.LCLObject, Mess);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TGtk2WSCustomListBox.GetItemIndex(const ACustomListBox: TCustomListBox
|
class function TGtk2WSCustomListBox.GetItemIndex(
|
||||||
): integer;
|
const ACustomListBox: TCustomListBox): integer;
|
||||||
var
|
var
|
||||||
Handle: HWND;
|
Handle: HWND;
|
||||||
Widget: PGtkWidget;
|
Widget: PGtkWidget;
|
||||||
@ -286,17 +286,16 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TGtk2WSCustomListBox.GetTopIndex(const ACustomListBox: TCustomListBox
|
class function TGtk2WSCustomListBox.GetTopIndex(
|
||||||
): integer;
|
const ACustomListBox: TCustomListBox): integer;
|
||||||
begin
|
begin
|
||||||
Result:=inherited GetTopIndex(ACustomListBox);
|
Result:=inherited GetTopIndex(ACustomListBox);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class procedure TGtk2WSCustomListBox.SelectItem(const ACustomListBox: TCustomListBox;
|
class procedure TGtk2WSCustomListBox.SelectItem(
|
||||||
AIndex: integer; ASelected: boolean);
|
const ACustomListBox: TCustomListBox; AnIndex: integer; ASelected: boolean);
|
||||||
var
|
var
|
||||||
Handle: HWND;
|
Handle: HWND;
|
||||||
Widget: PGtkWidget; // pointer to gtk-widget (local use when neccessary)
|
Widget: PGtkWidget; // pointer to gtk-widget (local use when neccessary)
|
||||||
@ -309,7 +308,7 @@ begin
|
|||||||
ListStoreModel := gtk_tree_view_get_model(PGtkTreeView(Widget));
|
ListStoreModel := gtk_tree_view_get_model(PGtkTreeView(Widget));
|
||||||
Selection := gtk_tree_view_get_selection(PGtkTreeView(Widget));
|
Selection := gtk_tree_view_get_selection(PGtkTreeView(Widget));
|
||||||
|
|
||||||
if gtk_tree_model_iter_nth_child(ListStoreModel, @Iter, nil, AIndex) then begin
|
if gtk_tree_model_iter_nth_child(ListStoreModel, @Iter, nil, AnIndex) then begin
|
||||||
case ASelected of
|
case ASelected of
|
||||||
True:
|
True:
|
||||||
begin
|
begin
|
||||||
@ -325,7 +324,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class procedure TGtk2WSCustomListBox.SetBorder(const ACustomListBox: TCustomListBox);
|
class procedure TGtk2WSCustomListBox.SetBorder(
|
||||||
|
const ACustomListBox: TCustomListBox);
|
||||||
begin
|
begin
|
||||||
// TODO
|
// TODO
|
||||||
debugln('TGtk2WSCustomListBox.SetBorder TODO');
|
debugln('TGtk2WSCustomListBox.SetBorder TODO');
|
||||||
@ -451,20 +451,19 @@ begin
|
|||||||
SetCallbacks(p, WidgetInfo);
|
SetCallbacks(p, WidgetInfo);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class procedure TGtk2WSCustomListBox.SetCallbacks(const AGtkWidget: PGtkWidget;
|
class procedure TGtk2WSCustomListBox.SetCallbacks(
|
||||||
const AWidgetInfo: PWidgetInfo);
|
const AGtkWidget: PGtkWidget; const AWidgetInfo: PWidgetInfo);
|
||||||
var
|
var
|
||||||
Selection: PGtkTreeSelection;
|
Selection: PGtkTreeSelection;
|
||||||
begin
|
begin
|
||||||
TGtkWSBaseScrollingWinControl.SetCallbacks(AGtkWidget,AWidgetInfo);
|
TGtkWSBaseScrollingWinControl.SetCallbacks(AGtkWidget,AWidgetInfo);
|
||||||
TGtkWSWinControl.SetCallbacks(PGtkObject(AWidgetInfo^.CoreWidget), TComponent(AWidgetInfo^.LCLObject));
|
|
||||||
|
|
||||||
Selection := gtk_tree_view_get_selection(PGtkTreeView(AWidgetInfo^.CoreWidget));
|
Selection := gtk_tree_view_get_selection(PGtkTreeView(AWidgetInfo^.CoreWidget));
|
||||||
SignalConnect(PGtkWidget(Selection), 'changed', @Gtk2WS_ListBoxChange, AWidgetInfo);
|
SignalConnect(PGtkWidget(Selection), 'changed', @Gtk2WS_ListBoxChange, AWidgetInfo);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TGtk2WSCustomListBox.GetSelCount(const ACustomListBox: TCustomListBox
|
class function TGtk2WSCustomListBox.GetSelCount(
|
||||||
): integer;
|
const ACustomListBox: TCustomListBox): integer;
|
||||||
var
|
var
|
||||||
Handle: HWND;
|
Handle: HWND;
|
||||||
Widget: PGtkWidget; // pointer to gtk-widget (local use when neccessary)
|
Widget: PGtkWidget; // pointer to gtk-widget (local use when neccessary)
|
||||||
@ -482,8 +481,8 @@ begin
|
|||||||
g_list_free(Rows);
|
g_list_free(Rows);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TGtk2WSCustomListBox.GetSelected(const ACustomListBox: TCustomListBox;
|
class function TGtk2WSCustomListBox.GetSelected(
|
||||||
const AIndex: integer): boolean;
|
const ACustomListBox: TCustomListBox; const AIndex: integer): boolean;
|
||||||
var
|
var
|
||||||
Handle: HWND;
|
Handle: HWND;
|
||||||
Widget: PGtkWidget; // pointer to gtk-widget (local use when neccessary)
|
Widget: PGtkWidget; // pointer to gtk-widget (local use when neccessary)
|
||||||
@ -502,8 +501,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TGtk2WSCustomListBox.GetStrings(const ACustomListBox: TCustomListBox
|
class function TGtk2WSCustomListBox.GetStrings(
|
||||||
): TStrings;
|
const ACustomListBox: TCustomListBox): TStrings;
|
||||||
var
|
var
|
||||||
Widget: PGtkWidget;// pointer to gtk-widget
|
Widget: PGtkWidget;// pointer to gtk-widget
|
||||||
Handle: HWND;
|
Handle: HWND;
|
||||||
@ -523,21 +522,18 @@ begin
|
|||||||
csCheckListBox, csListBox:
|
csCheckListBox, csListBox:
|
||||||
begin
|
begin
|
||||||
Widget := GetWidgetInfo(Pointer(Handle), True)^.CoreWidget;
|
Widget := GetWidgetInfo(Pointer(Handle), True)^.CoreWidget;
|
||||||
Result := TGtkListStoreStringList.Create(gtk_tree_view_get_model(PGtkTreeView(Widget)),
|
Result := TGtkListStoreStringList.Create(
|
||||||
|
gtk_tree_view_get_model(PGtkTreeView(Widget)),
|
||||||
Ord(ACustomListBox.fCompStyle = csCheckListBox) ,ACustomListBox);
|
Ord(ACustomListBox.fCompStyle = csCheckListBox) ,ACustomListBox);
|
||||||
if ACustomListBox is TCustomListBox then
|
TGtkListStoreStringList(Result).Sorted := ACustomListBox.Sorted;
|
||||||
TGtkListStoreStringList(Result).Sorted := ACustomListBox.Sorted;
|
|
||||||
end;
|
end;
|
||||||
else
|
else
|
||||||
raise Exception.Create('TGtk2WSCustomListBox.GetStrings');
|
raise Exception.Create('TGtk2WSCustomListBox.GetStrings');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TGtk2WSCustomCheckBox }
|
{ TGtk2WSCustomCheckBox }
|
||||||
|
|
||||||
|
|
||||||
class function TGtk2WSCustomCheckBox.RetrieveState(
|
class function TGtk2WSCustomCheckBox.RetrieveState(
|
||||||
const ACustomCheckBox: TCustomCheckBox): TCheckBoxState;
|
const ACustomCheckBox: TCustomCheckBox): TCheckBoxState;
|
||||||
var
|
var
|
||||||
|
146
lcl/lclproc.pas
146
lcl/lclproc.pas
@ -114,11 +114,18 @@ function CompareLineInfoCacheItems(Data1, Data2: Pointer): integer;
|
|||||||
function CompareAddrWithLineInfoCacheItem(Addr, Item: Pointer): integer;
|
function CompareAddrWithLineInfoCacheItem(Addr, Item: Pointer): integer;
|
||||||
|
|
||||||
|
|
||||||
|
type
|
||||||
|
TStringsSortCompare = function(const Item1, Item2: string): Integer;
|
||||||
|
|
||||||
|
|
||||||
|
procedure MergeSort(List: TFPList; const OnCompare: TListSortCompare);
|
||||||
|
procedure MergeSort(List: TStrings; const OnCompare: TStringsSortCompare);
|
||||||
|
|
||||||
function ShortCutToText(ShortCut: TShortCut): string;
|
function ShortCutToText(ShortCut: TShortCut): string;
|
||||||
function TextToShortCut(const ShortCutText: string): TShortCut;
|
function TextToShortCut(const ShortCutText: string): TShortCut;
|
||||||
|
|
||||||
function GetCompleteText(sText: string; iSelStart: Integer; bCaseSensitive, bSearchAscending: Boolean; slTextList: TStrings): string;
|
function GetCompleteText(sText: string; iSelStart: Integer;
|
||||||
|
bCaseSensitive, bSearchAscending: Boolean; slTextList: TStrings): string;
|
||||||
function IsEditableTextKey(Key: Word): Boolean;
|
function IsEditableTextKey(Key: Word): Boolean;
|
||||||
|
|
||||||
// Hooks used to prevent unit circles
|
// Hooks used to prevent unit circles
|
||||||
@ -166,6 +173,9 @@ function TruncToCardinal(const e: Extended): cardinal;
|
|||||||
function StrToDouble(const s: string): double;
|
function StrToDouble(const s: string): double;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// debugging
|
// debugging
|
||||||
procedure RaiseGDBException(const Msg: string);
|
procedure RaiseGDBException(const Msg: string);
|
||||||
procedure DumpExceptionBackTrace;
|
procedure DumpExceptionBackTrace;
|
||||||
@ -1085,6 +1095,140 @@ begin
|
|||||||
Result:=Double(StrToFloat(s));
|
Result:=Double(StrToFloat(s));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure MergeSort(List: TFPList; const OnCompare: TListSortCompare);
|
||||||
|
var
|
||||||
|
MergeList: PPointer;
|
||||||
|
|
||||||
|
procedure Merge(Pos1, Pos2, Pos3: integer);
|
||||||
|
// merge two sorted arrays
|
||||||
|
// the first array ranges Pos1..Pos2-1, the second ranges Pos2..Pos3
|
||||||
|
var Src1Pos,Src2Pos,DestPos,cmp,a:integer;
|
||||||
|
begin
|
||||||
|
while (Pos3>=Pos2) and (OnCompare(List[Pos2-1],List[Pos3])<=0) do
|
||||||
|
dec(Pos3);
|
||||||
|
if (Pos1>=Pos2) or (Pos2>Pos3) then exit;
|
||||||
|
Src1Pos:=Pos2-1;
|
||||||
|
Src2Pos:=Pos3;
|
||||||
|
DestPos:=Pos3;
|
||||||
|
while (Src2Pos>=Pos2) and (Src1Pos>=Pos1) do begin
|
||||||
|
cmp:=OnCompare(List[Src1Pos],List[Src2Pos]);
|
||||||
|
if cmp>0 then begin
|
||||||
|
MergeList[DestPos]:=List[Src1Pos];
|
||||||
|
dec(Src1Pos);
|
||||||
|
end else begin
|
||||||
|
MergeList[DestPos]:=List[Src2Pos];
|
||||||
|
dec(Src2Pos);
|
||||||
|
end;
|
||||||
|
dec(DestPos);
|
||||||
|
end;
|
||||||
|
while Src2Pos>=Pos2 do begin
|
||||||
|
MergeList[DestPos]:=List[Src2Pos];
|
||||||
|
dec(Src2Pos);
|
||||||
|
dec(DestPos);
|
||||||
|
end;
|
||||||
|
for a:=DestPos+1 to Pos3 do
|
||||||
|
List[a]:=MergeList[a];
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Sort(StartPos, EndPos: integer);
|
||||||
|
// sort an interval in List. Use MergeList as work space.
|
||||||
|
var
|
||||||
|
cmp, mid: integer;
|
||||||
|
p: Pointer;
|
||||||
|
begin
|
||||||
|
if StartPos=EndPos then begin
|
||||||
|
end else if StartPos+1=EndPos then begin
|
||||||
|
cmp:=OnCompare(List[StartPos],List[EndPos]);
|
||||||
|
if cmp>0 then begin
|
||||||
|
p:=List[StartPos];
|
||||||
|
List[StartPos]:=List[EndPos];
|
||||||
|
List[EndPos]:=p;
|
||||||
|
end;
|
||||||
|
end else if EndPos>StartPos then begin
|
||||||
|
mid:=(StartPos+EndPos) shr 1;
|
||||||
|
Sort(StartPos,mid);
|
||||||
|
Sort(mid+1,EndPos);
|
||||||
|
Merge(StartPos,mid+1,EndPos);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
if (List=nil) or (List.Count<=1) then exit;
|
||||||
|
ReAllocMem(MergeList,List.Count*SizeOf(Pointer));
|
||||||
|
Sort(0,List.Count-1);
|
||||||
|
Freemem(MergeList);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure MergeSort(List: TStrings; const OnCompare: TStringsSortCompare);
|
||||||
|
var
|
||||||
|
MergeList: PAnsiString;
|
||||||
|
|
||||||
|
procedure Merge(Pos1, Pos2, Pos3: integer);
|
||||||
|
// merge two sorted arrays
|
||||||
|
// the first array ranges Pos1..Pos2-1, the second ranges Pos2..Pos3
|
||||||
|
var Src1Pos,Src2Pos,DestPos,cmp,a:integer;
|
||||||
|
begin
|
||||||
|
while (Pos3>=Pos2) and (OnCompare(List[Pos2-1],List[Pos3])<=0) do
|
||||||
|
dec(Pos3);
|
||||||
|
if (Pos1>=Pos2) or (Pos2>Pos3) then exit;
|
||||||
|
Src1Pos:=Pos2-1;
|
||||||
|
Src2Pos:=Pos3;
|
||||||
|
DestPos:=Pos3;
|
||||||
|
while (Src2Pos>=Pos2) and (Src1Pos>=Pos1) do begin
|
||||||
|
cmp:=OnCompare(List[Src1Pos],List[Src2Pos]);
|
||||||
|
if cmp>0 then begin
|
||||||
|
MergeList[DestPos]:=List[Src1Pos];
|
||||||
|
dec(Src1Pos);
|
||||||
|
end else begin
|
||||||
|
MergeList[DestPos]:=List[Src2Pos];
|
||||||
|
dec(Src2Pos);
|
||||||
|
end;
|
||||||
|
dec(DestPos);
|
||||||
|
end;
|
||||||
|
while Src2Pos>=Pos2 do begin
|
||||||
|
MergeList[DestPos]:=List[Src2Pos];
|
||||||
|
dec(Src2Pos);
|
||||||
|
dec(DestPos);
|
||||||
|
end;
|
||||||
|
for a:=DestPos+1 to Pos3 do
|
||||||
|
List[a]:=MergeList[a];
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Sort(StartPos, EndPos: integer);
|
||||||
|
// sort an interval in List. Use MergeList as work space.
|
||||||
|
var
|
||||||
|
cmp, mid: integer;
|
||||||
|
s: string;
|
||||||
|
begin
|
||||||
|
if StartPos=EndPos then begin
|
||||||
|
end else if StartPos+1=EndPos then begin
|
||||||
|
cmp:=OnCompare(List[StartPos],List[EndPos]);
|
||||||
|
if cmp>0 then begin
|
||||||
|
s:=List[StartPos];
|
||||||
|
List[StartPos]:=List[EndPos];
|
||||||
|
List[EndPos]:=s;
|
||||||
|
end;
|
||||||
|
end else if EndPos>StartPos then begin
|
||||||
|
mid:=(StartPos+EndPos) shr 1;
|
||||||
|
Sort(StartPos,mid);
|
||||||
|
Sort(mid+1,EndPos);
|
||||||
|
Merge(StartPos,mid+1,EndPos);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
CurSize: PtrInt;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
if (List=nil) or (List.Count<=1) then exit;
|
||||||
|
CurSize:=PtrInt(List.Count)*SizeOf(Pointer);
|
||||||
|
ReAllocMem(MergeList,CurSize);
|
||||||
|
FillChar(MergeList^,CurSize,0);
|
||||||
|
Sort(0,List.Count-1);
|
||||||
|
for i:=0 to List.Count-1 do MergeList[i]:='';
|
||||||
|
Freemem(MergeList);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure InitializeDebugOutput;
|
procedure InitializeDebugOutput;
|
||||||
var
|
var
|
||||||
DebugFileName: string;
|
DebugFileName: string;
|
||||||
|
Loading…
Reference in New Issue
Block a user