diff --git a/App/READCOM.App.Globals.dfm b/App/READCOM.App.Globals.dfm index e485e81..635e139 100644 --- a/App/READCOM.App.Globals.dfm +++ b/App/READCOM.App.Globals.dfm @@ -27482,7 +27482,7 @@ object Globals: TGlobals item MultiResBitmap = < item - Size = 136 + Size = 30 end> IconName = 'Edit' SVGText = @@ -27527,7 +27527,7 @@ object Globals: TGlobals item MultiResBitmap = < item - Size = 136 + Size = 30 end> IconName = 'reverse' SVGText = @@ -27547,7 +27547,7 @@ object Globals: TGlobals item MultiResBitmap = < item - Size = 136 + Size = 30 end> IconName = 'play' SVGText = @@ -27567,8 +27567,8 @@ object Globals: TGlobals item MultiResBitmap = < item - Width = 87 - Height = 109 + Width = 24 + Height = 30 end> IconName = 'Diagram' SVGText = @@ -27664,7 +27664,7 @@ object Globals: TGlobals item MultiResBitmap = < item - Size = 136 + Size = 30 end> IconName = 'OpenFileFolder' SVGText = @@ -27700,7 +27700,7 @@ object Globals: TGlobals item MultiResBitmap = < item - Size = 136 + Size = 30 end> IconName = 'Save' SVGText = @@ -27797,7 +27797,7 @@ object Globals: TGlobals item MultiResBitmap = < item - Size = 136 + Size = 30 end> IconName = 'Plus' SVGText = @@ -27918,7 +27918,7 @@ object Globals: TGlobals item MultiResBitmap = < item - Size = 136 + Size = 30 end> IconName = 'Home' SVGText = @@ -27976,7 +27976,7 @@ object Globals: TGlobals item MultiResBitmap = < item - Size = 136 + Size = 30 end> IconName = 'Info' SVGText = @@ -28001,7 +28001,7 @@ object Globals: TGlobals item MultiResBitmap = < item - Size = 136 + Size = 30 end> IconName = 'Questionmark' SVGText = @@ -28041,7 +28041,7 @@ object Globals: TGlobals item MultiResBitmap = < item - Size = 136 + Size = 30 end> IconName = 'CopyAction' SVGText = @@ -28076,7 +28076,7 @@ object Globals: TGlobals item MultiResBitmap = < item - Size = 136 + Size = 30 end> IconName = 'PasteAction' SVGText = @@ -28126,7 +28126,7 @@ object Globals: TGlobals item MultiResBitmap = < item - Size = 136 + Size = 30 end> IconName = 'FlipHorizontally' SVGText = @@ -28162,7 +28162,7 @@ object Globals: TGlobals item MultiResBitmap = < item - Size = 136 + Size = 30 end> IconName = 'FlipVertically' SVGText = @@ -28198,7 +28198,7 @@ object Globals: TGlobals item MultiResBitmap = < item - Size = 136 + Size = 30 end> IconName = 'ThoughtEllipsis' SVGText = @@ -28226,7 +28226,7 @@ object Globals: TGlobals item MultiResBitmap = < item - Size = 136 + Size = 30 end> IconName = 'Timer' SVGText = @@ -28258,7 +28258,7 @@ object Globals: TGlobals item MultiResBitmap = < item - Size = 136 + Size = 30 end> IconName = 'FramedPicture' SVGText = @@ -28301,7 +28301,7 @@ object Globals: TGlobals item MultiResBitmap = < item - Size = 136 + Size = 30 end> IconName = 'READ-COM square' SVGText = @@ -28394,7 +28394,7 @@ object Globals: TGlobals item MultiResBitmap = < item - Size = 136 + Size = 30 end> IconName = 'Scissors' SVGText = @@ -28464,7 +28464,7 @@ object Globals: TGlobals item MultiResBitmap = < item - Size = 136 + Size = 30 end> IconName = 'Sun' SVGText = @@ -28587,7 +28587,7 @@ object Globals: TGlobals item MultiResBitmap = < item - Size = 136 + Size = 30 end> IconName = 'Gear8Teeth' SVGText = @@ -28681,32 +28681,32 @@ object Globals: TGlobals Layers = < item Name = 'Edit' - SourceRect.Right = 136.000000000000000000 - SourceRect.Bottom = 136.000000000000000000 + SourceRect.Right = 30.000000000000000000 + SourceRect.Bottom = 30.000000000000000000 end> end item Layers = < item Name = 'reverse' - SourceRect.Right = 136.000000000000000000 - SourceRect.Bottom = 136.000000000000000000 + SourceRect.Right = 30.000000000000000000 + SourceRect.Bottom = 30.000000000000000000 end> end item Layers = < item Name = 'play' - SourceRect.Right = 136.000000000000000000 - SourceRect.Bottom = 136.000000000000000000 + SourceRect.Right = 30.000000000000000000 + SourceRect.Bottom = 30.000000000000000000 end> end item Layers = < item Name = 'Diagram' - SourceRect.Right = 109.000000000000000000 - SourceRect.Bottom = 109.000000000000000000 + SourceRect.Right = 30.000000000000000000 + SourceRect.Bottom = 30.000000000000000000 end> end item @@ -28729,16 +28729,16 @@ object Globals: TGlobals Layers = < item Name = 'OpenFileFolder' - SourceRect.Right = 136.000000000000000000 - SourceRect.Bottom = 136.000000000000000000 + SourceRect.Right = 30.000000000000000000 + SourceRect.Bottom = 30.000000000000000000 end> end item Layers = < item Name = 'Save' - SourceRect.Right = 136.000000000000000000 - SourceRect.Bottom = 136.000000000000000000 + SourceRect.Right = 30.000000000000000000 + SourceRect.Bottom = 30.000000000000000000 end> end item @@ -28761,8 +28761,8 @@ object Globals: TGlobals Layers = < item Name = 'Plus' - SourceRect.Right = 136.000000000000000000 - SourceRect.Bottom = 136.000000000000000000 + SourceRect.Right = 30.000000000000000000 + SourceRect.Bottom = 30.000000000000000000 end> end item @@ -28785,8 +28785,8 @@ object Globals: TGlobals Layers = < item Name = 'Home' - SourceRect.Right = 136.000000000000000000 - SourceRect.Bottom = 136.000000000000000000 + SourceRect.Right = 30.000000000000000000 + SourceRect.Bottom = 30.000000000000000000 end> end item @@ -28801,96 +28801,96 @@ object Globals: TGlobals Layers = < item Name = 'Info' - SourceRect.Right = 136.000000000000000000 - SourceRect.Bottom = 136.000000000000000000 + SourceRect.Right = 30.000000000000000000 + SourceRect.Bottom = 30.000000000000000000 end> end item Layers = < item Name = 'Questionmark' - SourceRect.Right = 136.000000000000000000 - SourceRect.Bottom = 136.000000000000000000 + SourceRect.Right = 30.000000000000000000 + SourceRect.Bottom = 30.000000000000000000 end> end item Layers = < item Name = 'CopyAction' - SourceRect.Right = 136.000000000000000000 - SourceRect.Bottom = 136.000000000000000000 + SourceRect.Right = 30.000000000000000000 + SourceRect.Bottom = 30.000000000000000000 end> end item Layers = < item Name = 'PasteAction' - SourceRect.Right = 136.000000000000000000 - SourceRect.Bottom = 136.000000000000000000 + SourceRect.Right = 30.000000000000000000 + SourceRect.Bottom = 30.000000000000000000 end> end item Layers = < item Name = 'FlipHorizontally' - SourceRect.Right = 136.000000000000000000 - SourceRect.Bottom = 136.000000000000000000 + SourceRect.Right = 30.000000000000000000 + SourceRect.Bottom = 30.000000000000000000 end> end item Layers = < item Name = 'FlipVertically' - SourceRect.Right = 136.000000000000000000 - SourceRect.Bottom = 136.000000000000000000 + SourceRect.Right = 30.000000000000000000 + SourceRect.Bottom = 30.000000000000000000 end> end item Layers = < item Name = 'ThoughtEllipsis' - SourceRect.Right = 136.000000000000000000 - SourceRect.Bottom = 136.000000000000000000 + SourceRect.Right = 30.000000000000000000 + SourceRect.Bottom = 30.000000000000000000 end> end item Layers = < item Name = 'Timer' - SourceRect.Right = 136.000000000000000000 - SourceRect.Bottom = 136.000000000000000000 + SourceRect.Right = 30.000000000000000000 + SourceRect.Bottom = 30.000000000000000000 end> end item Layers = < item Name = 'FramedPicture' - SourceRect.Right = 136.000000000000000000 - SourceRect.Bottom = 136.000000000000000000 + SourceRect.Right = 30.000000000000000000 + SourceRect.Bottom = 30.000000000000000000 end> end item Layers = < item Name = 'READ-COM square' - SourceRect.Right = 136.000000000000000000 - SourceRect.Bottom = 136.000000000000000000 + SourceRect.Right = 30.000000000000000000 + SourceRect.Bottom = 30.000000000000000000 end> end item Layers = < item Name = 'Scissors' - SourceRect.Right = 136.000000000000000000 - SourceRect.Bottom = 136.000000000000000000 + SourceRect.Right = 30.000000000000000000 + SourceRect.Bottom = 30.000000000000000000 end> end item Layers = < item Name = 'Sun' - SourceRect.Right = 136.000000000000000000 - SourceRect.Bottom = 136.000000000000000000 + SourceRect.Right = 30.000000000000000000 + SourceRect.Bottom = 30.000000000000000000 end> end item @@ -28913,8 +28913,8 @@ object Globals: TGlobals Layers = < item Name = 'Gear8Teeth' - SourceRect.Right = 136.000000000000000000 - SourceRect.Bottom = 136.000000000000000000 + SourceRect.Right = 30.000000000000000000 + SourceRect.Bottom = 30.000000000000000000 end> end item diff --git a/App/READCOM.App.Models.pas b/App/READCOM.App.Models.pas index 8987357..cdfad23 100644 --- a/App/READCOM.App.Models.pas +++ b/App/READCOM.App.Models.pas @@ -154,6 +154,9 @@ interface function IsBorderVisible: Boolean; procedure SetBorderVisible(const Value: Boolean); + {Root} + function IsRoot: Boolean; + {Home} function IsHome: Boolean; //note: a Home StoryItem doesn't have to be StoryPoint, could be just the startup instructions that are shown once and not when looping through the StoryPoints procedure SetHome(const Value: Boolean); diff --git a/App/READCOM_App.dproj b/App/READCOM_App.dproj index ca14587..e76a444 100644 --- a/App/READCOM_App.dproj +++ b/App/READCOM_App.dproj @@ -4,8 +4,8 @@ 19.4 FMX True - Release - Android64 + Debug + Win32 168979 Application READCOM_App.dpr @@ -449,6 +449,13 @@
MessageForm
+ +
FMXObjectDebuggerFrame
+ TFrame +
+ +
ObjectDebuggerFMXForm
+
diff --git a/App/Views/READCOM.Views.Main.pas b/App/Views/READCOM.Views.Main.pas index d17785e..5b1813f 100644 --- a/App/Views/READCOM.Views.Main.pas +++ b/App/Views/READCOM.Views.Main.pas @@ -167,7 +167,8 @@ TMainForm = class(TForm, IStory) MainForm: TMainForm; resourcestring - MSG_CONFIRM_CLEAR_STORY = 'Clearing story: are you sure?'; + MSG_CONFIRM_CLEAR_STORY = 'Clearing Story: are you sure?'; + MSG_CONFIRM_DELETION = 'Deleting ActiveStoryItem: are you sure?'; implementation uses @@ -787,32 +788,39 @@ procedure TMainForm.DeleteActiveStoryItem; //Note: make sure any keyboard action begin if not Assigned(ActiveStoryItem) then exit; - if (Assigned(RootStoryItem) and (ActiveStoryItem.View <> RootStoryItem.View)) then //Note: don't compare IStoryItem interfaces with "=", compare the TStoryItem components they correspond to (getting their "View") - ActiveStoryItem.Delete //this makes ParentStoryItem active (which updates StructureView) - else //note: confirmation is only done at "HUDactionCutExecute" - NewRootStoryItem; //deleting the RootStoryItem via "NewRootStoryItem", but not via "HUD.actionNew.Execute" since that also tries "LoadDefaultDocument" first //RootStoryItem change updates StructureView + if ActiveStoryItem.IsRoot then + NewRootStoryItem //deleting the RootStoryItem via "NewRootStoryItem", but not via "HUD.actionNew.Execute" since that also tries "LoadDefaultDocument" first //RootStoryItem change updates StructureView //note: confirmation is only done at "HUDactionCutExecute" + else + ActiveStoryItem.Delete; //this makes ParentStoryItem active (which updates StructureView) end; procedure TMainForm.CutActiveStoryItem; //Note: make sure any keyboard actions call the action event handlers since only those do confirmation begin if not Assigned(ActiveStoryItem) then exit; - if (Assigned(RootStoryItem) and (ActiveStoryItem.View <> RootStoryItem.View)) then - ActiveStoryItem.Cut //this makes ParentStoryItem active (which updates StructureView) - else //note: confirmation is only done at "HUDactionCutExecute" + if ActiveStoryItem.IsRoot then begin ActiveStoryItem.Copy; //needed to simulate "Cut" - NewRootStoryItem; //deleting the RootStoryItem via "NewRootStoryItem", but not via "HUD.actionNew.Execute" since that also tries "LoadDefaultDocument" first //RootStoryItem change updates StructureView - end; + NewRootStoryItem; //deleting the RootStoryItem via "NewRootStoryItem", but not via "HUD.actionNew.Execute" since that also tries "LoadDefaultDocument" first //RootStoryItem change updates StructureView //note: confirmation is only done at "HUDactionCutExecute" + end + else + ActiveStoryItem.Cut //this makes ParentStoryItem active (which updates StructureView) end; {$endregion} procedure TMainForm.HUDactionDeleteExecute(Sender: TObject); begin - if not HUD.EditMode then exit; //only in Edit mode + if not (HUD.EditMode and Assigned(ActiveStoryItem)) then exit; //only in Edit mode (plus safety check for ActiveStoryItem) - TApplication.Confirm(MSG_CONFIRM_CLEAR_STORY, //confirmation done only at the action level //Note: could also use Application.Confirm since Confirm is defined as a class function in ApplicationHelper (and those can be called on object instances of the respective class too) + var msg: String; + if ActiveStoryItem.IsRoot then + msg := MSG_CONFIRM_CLEAR_STORY + else + msg := MSG_CONFIRM_DELETION; + + //Always confirming for destructive actions like deletion + TApplication.Confirm(msg, //confirmation done only at the action level //Note: could also use Application.Confirm since Confirm is defined as a class function in ApplicationHelper (and those can be called on object instances of the respective class too) procedure(Confirmed: Boolean) begin if Confirmed then @@ -823,15 +831,19 @@ procedure TMainForm.HUDactionDeleteExecute(Sender: TObject); procedure TMainForm.HUDactionCutExecute(Sender: TObject); begin - if not HUD.EditMode then exit; //only in Edit mode + if not (HUD.EditMode and Assigned(ActiveStoryItem)) then exit; //only in Edit mode (plus safety check for ActiveStoryItem) - TApplication.Confirm(MSG_CONFIRM_CLEAR_STORY, //confirmation done only at the action level //Note: could also use Application.Confirm since Confirm is defined as a class function in ApplicationHelper (and those can be called on object instances of the respective class too) - procedure(Confirmed: Boolean) - begin - if Confirmed then - CutActiveStoryItem; - end - ); + //Not considering Cut a destructive action since one can Paste back. However when cutting the RootStoryItem, since it has no parent to be activated and a new RootStoryItem will be created, paste back means it will become a child of the new RootStoryItem, so asking for confirmation only when cutting the RootStoryItem + if ActiveStoryItem.IsRoot then + TApplication.Confirm(MSG_CONFIRM_CLEAR_STORY, //confirmation done only at the action level //Note: could also use Application.Confirm since Confirm is defined as a class function in ApplicationHelper (and those can be called on object instances of the respective class too) + procedure(Confirmed: Boolean) + begin + if Confirmed then + CutActiveStoryItem; + end + ) + else + CutActiveStoryItem; //no confirmation for cutting non-Root StoryItems end; procedure TMainForm.HUDactionCopyExecute(Sender: TObject); diff --git a/App/Views/READCOM.Views.StoryItem.pas b/App/Views/READCOM.Views.StoryItem.pas index d9cd285..4ab61ab 100644 --- a/App/Views/READCOM.Views.StoryItem.pas +++ b/App/Views/READCOM.Views.StoryItem.pas @@ -122,10 +122,11 @@ TStoryItem = class(TCustomManipulator, IStoryItem, IClipboardEnabled, IStoreab function IsActive: Boolean; virtual; procedure SetActive(const Value: Boolean); virtual; - {HomeStoryItem} - class procedure SetHomeStoryItem(const Value: IStoryItem); static; //static means has no "Self" passed to it, required for "class property" accessors + {Root} + function IsRoot: Boolean; {Home} + class procedure SetHomeStoryItem(const Value: IStoryItem); static; //static means has no "Self" passed to it, required for "class property" accessors function IsHome: Boolean; virtual; procedure SetHome(const Value: Boolean); virtual; @@ -671,6 +672,11 @@ procedure TStoryItem.SetActive(const Value: Boolean); PlayRandomAudioStoryItem; //TODO: maybe should play AudioStoryItems in the order they exist in their parent StoryItem (but would need to remember last one played in that case which may be problematic if they are reordered etc.) end; +function TStoryItem.IsRoot: Boolean; +begin + result := not Assigned(ParentStoryItem); +end; + procedure TStoryItem.ActivateParentStoryItem; begin var parentItem := ParentStoryItem; @@ -1223,7 +1229,10 @@ procedure TStoryItem.MouseClick(Button: TMouseButton; Shift: TShiftState; X, Y: var LActiveStoryItemParent := ActiveStoryItem.ParentStoryItem; if not Assigned(LActiveStoryItemParent) then exit(false); //ActiveStoryItem is the RootStoryItem, so we can't be its Sibling - result := (LActiveStoryItemParent.View = ParentStoryItem.View); //check if we have the same parent as the ActiveStoryItem //Note: we can't compare the IStoryPoint interfaces directly, must compare the TStoryPoint objects they wrap (the views) + var LParent := ParentStoryItem; + if not Assigned(LParent) then exit(false); //we're the RootStoryItem, so we can't have Siblings + + result := (LActiveStoryItemParent.View = LParent.View); //check if we have the same parent as the ActiveStoryItem //Note: we can't compare the IStoryPoint interfaces directly, must compare the TStoryPoint objects they wrap (the views) end; begin @@ -1244,8 +1253,8 @@ procedure TStoryItem.MouseClick(Button: TMouseButton; Shift: TShiftState; X, Y: else begin - if ((ssCtrl in Shift) or (ssRight in Shift)) and //either Ctrl+LeftClick or just RightClick - HasActiveChildStoryItem or HasActiveSiblingStoryItem then //and one of our children is the ActiveStoryItem... + if (((ssCtrl in Shift) or (ssRight in Shift)) and //either Ctrl+LeftClick or just RightClick + (HasActiveChildStoryItem or HasActiveSiblingStoryItem)) then //and (one of our children is the ActiveStoryItem or we're its Sibling)... Active := true //...make us (the parent of the ActiveStoryItem) the Active one (so that we can go back to the parent level by right-clicking it without using the keyboard's ESC key) else begin