123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- unit designer;
- {$mode objfpc}
- interface
- uses
- Classes, SysUtils, libjquery, webwidget, htmlwidgets, contnrs, js, web, webideclient;
- Type
- { TRegisteredWidget }
- TRegisteredWidget = Class
- Private
- FClass : TWebwidgetClass;
- FImageName : String;
- Public
- Constructor Create(aClass : TWebwidgetClass; aImageName : String);
- Property WidgetClass : TWebwidgetClass Read FClass;
- Property ImageName : String Read FimageName;
- end;
- TWidgetButtonWidget = Class(TButtonWidget)
- MyWidget : TRegisteredWidget;
- end;
- TSortable = Class helper for TJQuery
- Procedure sortable(Options : TJSObject); external name 'sortable'; overload;
- Procedure sortable(Options : string); external name 'sortable'; overload;
- end;
- { TDesignDemo }
- TDesignDemo = class(TComponent)
- private
- FIDEClient: TIDEClient;
- procedure AddWidgetByName(aID: NativeInt; AName: String);
- function CreateNewWidget(aParent: TCustomWebWidget; aClass: TCustomWebWidgetClass): TCustomWebWidget;
- function DoActive(Event: TEventListenerEvent): boolean;
- procedure DoCommandsReceived(Sender: TObject; aCommands: TJSArray);
- procedure DoWidgetAddClick(Sender: TObject; Event: TJSEvent);
- procedure SetIDEClient(AValue: TIDEClient);
- function SortableOptions: TJSObject;
- function StreamWidget(aWidget: TCustomWebWidget): String;
- Public
- FConfirmAdd : NativeInt;
- FAddWidget : TRegisteredWidget;
- FPage : TWebPage;
- FToolBar : TContainerWidget;
- FButtons : Array[1..10] of TButtonWidget;
- FWidgetButtons : Array of TWidgetButtonWidget;
- FRegisteredWidgets : TObjectList;
- Constructor Create(aOwner : TComponent); override;
- Destructor Destroy; override;
- Procedure RegisterWidgets;
- Procedure RegisterWidget(aClass : TWebWidgetClass; aImageName : String);
- procedure SetAddMode(aRegisteredWidget: TRegisteredWidget);
- Procedure FillToolBar;
- Procedure SetupPage;
- property IDEClient: TIDEClient Read FIDEClient Write SetIDEClient;
- end;
- implementation
- Const
- SSortableSelect = '#designpage, #designpage [data-ww-element-content]';
- Type
- { TJumboWidget }
- TJumboWidget = class(TSimpleTemplateWidget)
- Public
- Constructor Create(aOwner: TComponent); override;
- end;
- type
- TWidgetHack = Class(TCustomWebWidget)
- Property Element;
- Property ElementID;
- Property TopElement;
- Property ContentElement;
- end;
- TPageHack = Class(TWebPage)
- Property Element;
- Property ElementID;
- end;
- { TJumboWidget }
- constructor TJumboWidget.Create(aOwner: TComponent);
- begin
- inherited Create(aOwner);
- Template:='<div class="jumbotron">'+sLineBreak+
- '<h1 class="display-4">Hello, world!</h1>'+sLineBreak+
- '<p class="lead">This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.</p>'+sLineBreak+
- '<hr class="my-4">'+sLineBreak+
- '<p>It uses utility classes for typography and spacing to space content out within the larger container.</p>'+sLineBreak+
- '<p class="lead">'+sLineBreak+
- ' <a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a>'+sLineBreak+
- '</p>'+sLineBreak+
- '</div>';
- end;
- { TRegisteredWidget }
- constructor TRegisteredWidget.Create(aClass: TWebwidgetClass; aImageName: String);
- begin
- FClass:=aClass;
- FImageName:=aImageName;
- end;
- { TDesignDemo }
- function TDesignDemo.CreateNewWidget(aParent : TCustomWebWidget; aClass : TCustomWebWidgetClass) : TCustomWebWidget;
- begin
- Result:=aClass.Create(FPage);
- Result.Name:=Result.ClassName+IntToStr(FPage.ChildCount);
- Result.Parent:=aParent;
- Result.Refresh;
- if Assigned(IDEClient) then
- IDEClient.SendAction('create',New(['widget',Result.Name,'class',Result.ClassName]));
- end;
- function TDesignDemo.StreamWidget(aWidget : TCustomWebWidget) : String;
- Var
- S: TBytesStream;
- T : TStringStream;
- begin
- T:=Nil;
- S:=TBytesStream.Create(Nil);
- try
- S.WriteComponent(aWidget);
- S.Position:=0;
- T:=TStringStream.Create('');
- ObjectBinaryToText(S,T);
- Result:=T.DataString;
- finally
- T.Free;
- S.Free;
- end;
- end;
- function TDesignDemo.DoActive(Event: TEventListenerEvent): boolean;
- Const
- Toolbar = '<div class="designerToolbar">' +
- '<div class="designerDragHandle ui-icon ui-icon-arrow-4"></div>' +
- '<div class="designerDelete ui-icon ui-icon-trash"></div>' +
- '</div>';
- var
- aParent,aNew : TCustomWebWidget;
- aNewActive : TJSHTMLElement;
- aNewWidget : TRegisteredWidget;
- begin
- Result:=True;
- JQuery('.designerActive').removeClass('designerActive');
- JQuery('.designerToolbar').remove();
- aNewActive:=TJSHTMLElement(event.target);
- aParent:=FPage.FindWidgetByID(String(aNewActive.dataset[STopElementData]));
- if aParent=Nil then
- aParent:=FPage;
- if (FAddWidget<>Nil) then
- begin
- aNewWidget:=FAddWidget;
- FAddWidget:=Nil;
- if aParent<>Nil then
- begin
- aNew:=CreateNewWidget(aParent,aNewWidget.WidgetClass);
- aNewActive:=TWidgetHack(aNew).TopElement;
- if Assigned(TWidgetHack(aNew).ContentElement) then
- JQuery(TWidgetHack(aNew).ContentElement).Sortable(SortableOptions);
- jQuery(aNewActive).on_('click',@DoActive);
- aParent:=aNew;
- end;
- end;
- JQuery(aNewActive).AddClass('designerActive').prepend(toolbar);
- if assigned(aParent) and Assigned(IDEClient) then
- IDEClient.SendAction('select',New(['widget',aParent.Name,'class',aParent.ClassName,'state',StreamWidget(aParent)]));
- end;
- procedure TDesignDemo.SetAddMode(aRegisteredWidget : TRegisteredWidget);
- begin
- FAddWidget:=aRegisteredWidget;
- end;
- procedure TDesignDemo.DoWidgetAddClick(Sender: TObject; Event: TJSEvent);
- begin
- SetAddMode((Sender as TWidgetButtonWidget).MyWidget);
- end;
- procedure TDesignDemo.AddWidgetByName(aID : NativeInt; AName : String);
- Var
- I : integer;
- Btn : TWidgetButtonWidget;
- begin
- I:=FRegisteredWidgets.Count-1;
- While (i>=0) and Not SameText(TRegisteredWidget(FRegisteredWidgets[i]).WidgetClass.ClassName,aName) do
- Dec(I);
- if I<0 then exit;
- SetAddMode(TRegisteredWidget(FRegisteredWidgets[i]));
- FConfirmAdd:=aID;
- end;
- procedure TDesignDemo.DoCommandsReceived(Sender: TObject; aCommands: TJSArray);
- var
- J,P : TJSOBject;
- aName : String;
- aID : NativeInt;
- I : integer;
- begin
- for I:=0 to aCommands.Length-1 do
- begin
- J:=TJSObject(aCommands[i]);
- aName:=String(J['name']);
- aID:=NativeInt(J['id']);
- p:=TJSObject(J['payload']);
- case aName of
- 'addWidget' : AddWidgetByName(aID,String(P['class']));
- end;
- end;
- end;
- procedure TDesignDemo.SetIDEClient(AValue: TIDEClient);
- begin
- if FIDEClient=AValue then Exit;
- FIDEClient:=AValue;
- if assigned(FIDEClient) then
- begin
- FIDEClient.OnCommands:=@DoCommandsReceived;
- FIDEClient.StartCommandPolling;
- FToolBar.Visible:=False;
- end;
- end;
- function TDesignDemo.SortableOptions: TJSObject;
- begin
- Result:=New([
- 'items','> [data-ww-element-top]',
- 'connectWith','[data-ww-element-content]',
- 'placeholder','designerPlaceholder',
- 'tolerance','pointer',
- // 'containment',TPageHack(FPage).Element,
- // 'handle','[data-ww-element-top]',
- 'cancel',''
- ]);
- end;
- constructor TDesignDemo.Create(aOwner: TComponent);
- begin
- inherited Create(aOwner);
- FRegisteredWidgets:=TObjectList.Create;
- RegisterWidgets;
- FillToolBar;
- SetUpPage;
- // []
- JQuery(SSortableSelect).Sortable(SortableOptions);
- jQuery('#designpage').on_('click','[data-ww-element-top]',@DoActive);
- jQuery('#designpage').on_('click',@DoActive);
- end;
- destructor TDesignDemo.Destroy;
- begin
- FreeAndNil(FRegisteredWidgets);
- inherited Destroy;
- end;
- procedure TDesignDemo.RegisterWidgets;
- begin
- RegisterWidget(TButtonWidget,'button');
- RegisterWidget(TCheckBoxInputWidget,'checkbox');
- RegisterWidget(TRadioInputWidget,'radio');
- RegisterWidget(TTextInputWidget,'edit');
- RegisterWidget(TImageWidget,'image');
- RegisterWidget(TTextAreaWidget,'memo');
- RegisterWidget(TSelectWidget,'select');
- RegisterWidget(TContainerWidget,'container');
- RegisterWidget(TJumboWidget,'jumbo');
- end;
- procedure TDesignDemo.RegisterWidget(aClass: TWebWidgetClass; aImageName: String);
- begin
- FRegisteredWidgets.Add(TRegisteredWidget.Create(aClass,aImageName));
- end;
- procedure TDesignDemo.SetupPage;
- Const
- ButtonClasses : Array[0..8] of string
- = ('primary','secondary','success','danger','warning','info','light','dark','link');
- var
- I : Integer;
- begin
- FPage:=TWebPage.Create(Self);
- FPage.ElementID:='designpage';
- FPage.Refresh;
- For I:=0 to 9 do
- begin
- FButtons[I]:=TWidgetButtonWidget.Create(FPage);
- FButtons[I].Classes:='btn btn-'+ButtonClasses[I mod 9];
- FButtons[I].Text:='Button #'+IntToStr(I+1);
- FButtons[I].Parent:=FPage;
- FButtons[I].Refresh;
- end;
- end;
- procedure TDesignDemo.FillToolBar;
- Var
- RW : TRegisteredWidget;
- I : Integer;
- Btn : TWidgetButtonWidget;
- begin
- FToolBar:=TContainerWidget.Create(Self);
- FToolbar.Styles.EnsureStyle('min-height','34px');
- FToolbar.Styles.RemoveStyle('width');
- FToolbar.Styles.RemoveStyle('height');
- FToolbar.ElementId:='toolbar';
- FToolbar.Refresh;
- SetLength(FWidgetButtons,FRegisteredWidgets.Count);
- For I:=0 to FRegisteredWidgets.Count-1 do
- begin
- RW:=TRegisteredWidget(FRegisteredWidgets[I]);
- Btn:=TWidgetButtonWidget.Create(Self);
- FWidgetButtons[I]:=Btn;
- Btn.MyWidget:=RW;
- Btn.Classes:='btn btn-light';
- Btn.Text:='';
- Btn.Parent:=FToolbar;
- Btn.Styles.Add('background-image','url("widgets/'+RW.ImageName+'.png")');
- Btn.Refresh;
- Btn.Data['widgetClass']:=RW.WidgetClass.ClassName;
- Btn.OnClick:=@DoWidgetAddClick;
- end;
- end;
- end.
|