Archive

Archive for February, 2013

Smart Mobile Studio, Creating a TScrollbox

February 28, 2013 Leave a comment

What would Delphi be without TScrollbox? Well probably just as great, but we all know how helpful TScrollbox is and how (with a bit of subclassing) what it can do. But what about Smart Mobile Studio and Smart pascal? Can we get the same functionality in the browser? Indeed we can, and here is the latest addition to the growing list of standard Smart Mobile Studio component palette: TW3Scrollbox.

TW3Scrollbox

TW3Scrollbox

With the scrollbars under wraps it’s actually not that hard to make. I must warn you though that the upcoming 1.1 final release of Smart Mobile Studio have some minor changes behind the scenes. So you wont be able to compile this without removing the childAdded override and the w3_DOMReady call). Also, as so many have requested, we have separated each component into their own units – this gives you even more compact apps when you compile (although the linker is actually very, very good at removing code that is not used).

The interface for our scrollbox is fairly straight forward:

unit w3scrollbox;

interface

uses w3system, w3components, w3graphics, w3scrollbar;

  //Default size of the scrollbars
  const
  CNT_SCROLLBAR_SIZE  = 18;

type

  TW3ScrollBoxContainer = Class(TW3CustomControl)
  End;

  TW3Scrollbox = Class(TW3CustomControl)
  Private
    FHScroll: TW3HorizontalScrollbar;
    FVScroll: TW3VerticalScrollbar;
    FContent: TW3ScrollBoxContainer;
    Procedure HandleScroll(sender:TObject);
    Procedure UpdateWhenReady;
  protected
    procedure ChildAdded(Const aChild:TW3Component);override;
    procedure InitializeObject; override;
    procedure FinalizeObject; override;
    procedure Resize; override;
  public
    Property  Content:TW3ScrollBoxContainer read FContent;
    Procedure Update;
  End;

And as expected, so is the implementation. You may wonder what the “updateWhenReady” method does? Well, since your child objects will be created via the constructor under smart – the JavaScript browser code might not be ready when ChildAdded() is called (which is invoked whenever a child control attach as a child). So what we do here is that we wait until both the DOM (document object model) and TApplication instance is truly ready – then we automatically update the scrollbars if there is any content that is larger than the client-area.


implementation


  //###########################################################################
  // TW3Scrollbox
  //###########################################################################

  procedure TW3Scrollbox.InitializeObject;
  Begin
    inherited;
    FContent:=TW3ScrollBoxContainer.Create(self);

    FHScroll:=TW3HorizontalScrollbar.Create(self);
    FHScroll.OnChanged:=HandleScroll;
    FHScroll.visible:=False;

    FVScroll:=TW3VerticalScrollbar.create(self);
    FVScroll.OnChanged:=HandleScroll;
    FVScroll.visible:=False;

    //UpdateWhenReady;
  end;

  procedure TW3Scrollbox.FinalizeObject;
  Begin
    FHScroll.free;
    FVScroll.free;
    FContent.free;
    inherited;
  end;

  procedure TW3Scrollbox.ChildAdded(Const aChild:TW3Component);
  Begin
    inherited ChildAdded(aChild);
    UpdateWhenReady;
  end;

  Procedure TW3Scrollbox.UpdateWhenReady;
  begin
    if (w3_DOMReady=False)
    or (ObjectReady=False) then
    w3_callback(updateWhenReady,10) else
    w3_callback(Update,1);
  end;

  procedure TW3Scrollbox.Resize;
  var
    wd,hd:  Integer;
  begin
    inherited;
    wd:=clientWidth;
    hd:=clientHeight;

    if FHScroll.visible then
    dec(hd,CNT_SCROLLBAR_SIZE);

    if FVScroll.Visible then
    dec(wd,CNT_SCROLLBAR_SIZE);

    if FHScroll.Visible then
    FHScroll.setBounds(0,hd,wd,CNT_SCROLLBAR_SIZE);

    if FVScroll.Visible then
    FVScroll.setBounds(wd,0,CNT_SCROLLBAR_SIZE,hd);

    FContent.SetBounds(1,1,wd-2,hd-2);
  end;

  Procedure TW3Scrollbox.HandleScroll(sender:TObject);
  Begin
    FContent.ScrollInfo.ScrollTo(FHScroll.Position,FVScroll.Position);
  end;

  Procedure TW3Scrollbox.Update;
  begin
    BeginUpdate;
    try
      if FContent.ScrollInfo.ScrollWidth>FContent.ClientWidth then
      Begin
        FHScroll.Total:=FContent.ScrollInfo.ScrollWidth;
        FHScroll.PageSize:=FContent.ClientWidth;
        If not FHScroll.Visible then
        Begin
          FHScroll.Visible:=True;
          self.SetWasSized;
        end;
      end;

      if FContent.ScrollInfo.ScrollHeight>FContent.clientHeight then
      Begin
        FVScroll.Total:=FContent.ScrollInfo.ScrollHeight;
        FVScroll.PageSize:=FContent.clientHeight;
        If not FVScroll.Visible then
        Begin
          FVScroll.Visible:=True;
          SetWasSized;
        end;
      end;

      FContent.SendToBack;

    finally
      EndUpdate;
    end;

  end;

end.

Using the scrollbox (without the designer) is straight forward. In this case i added a beatles poster i found on google to the project as a resource, inserted an image into the content of the scrollbox – and used the image as a background (as opposed to the image itself. Neat trick!).

  FBox:=TW3Scrollbox.Create(self);
  FBox.SetBounds(10,200,600,500);
  FBox.StyleClass:='TW3CustomControl';

  FTest:=TW3Image.Create(FBox.Content);
  FTest.Background.FromURL('res/beatles.jpg');
  FTest.setBounds(0,0,1644 * 2, 1086 * 2);

Smart Mobile Studio, creating a scrollbar

February 20, 2013 Leave a comment

What HTML5 really needs is a proper, native scrollbar that doesnt suck. I’ve had a look around the internet but the native javascript versions are either dependent on some hyped up library, rendering it almost useless (i dont need 40k of javascript just to get things scrolling) – or a part of a large framework that i have no time or patience to wrap.

Since we are adding more and more user controls to smart these days, why not add good o’l TScrollBar to the mix?

It took me less than one hour to knock this one together. That included making breakfast, having a latte and brushing my teeth. If you are looking for a serious toolbox for your HTML5 development kit — then no other development studio will save you as much time as Smart Mobile Studio (he said blatantly promoting his own creation). Ok, here goes:

Analyzing the problem

So, what is a scrollbar? In short it consists of 4 parts: an up arrow, a region to move a handle, the handle – and last but not least: a down arrow. The hard part is not to draw or setup the actual control, but rather to translate between screen coordinates and the values the scrollbar represents. The scrollbar might represent 100000 items of “something”, but since you have (for instance) only 400 pixels to represent that sum – you have to translate between the visual and the abstract.

I started by isolating the math in 3 methods:

  function TW3CustomScrollBar.calcSizeOfHandle:Integer;
  var
    mTemp:  Integer;
  Begin
    mTemp:=TInteger.PercentOfValue(PageSize,Total);
    result:=round( mTemp * getArea / 100);
  end;

  function TW3CustomScrollBar.PositionToPixelOffset(aPosition:Integer):Integer;
  var
    mTemp:  Integer;
  Begin
    mTemp:=TInteger.PercentOfValue(aPosition,Total);
    result:=round( mTemp * getArea / 100);
  end;

  function TW3CustomScrollBar.PixelOffsetToPosition(aPxPos:Integer):Integer;
  var
    mTemp: Integer;
  Begin
    mTemp:=TInteger.PercentOfValue(aPxPos,getarea);
    result:=trunc( (mTemp * Total) / 100 );
  end;

I know, I know – this could have been made so much simpler. But it was 06:45 in the morning and I had just woken up and I was out of redbull. So just go with it. Here is the baseclass in all it’s humble glory:

type

  TW3ScrollbarLowerBtn  = Class(TW3CustomControl);
  TW3ScrollbarHigherBtn = class(TW3CustomControl);
  TW3ScrollbarHandle    = class(TW3CustomControl);

  TW3CustomScrollBar = Class(TW3CustomControl)
  private
    FUpBtn:     TW3ScrollbarLowerBtn;
    FDownBtn:   TW3ScrollbarHigherBtn;
    FHandle:    TW3ScrollbarHandle;
    FTotal:     Integer;
    FPageSize:  Integer;
    FPosition:  Integer;
  protected
    Procedure   setTotal(aValue:Integer);virtual;
    procedure   setPageSize(aValue:Integer);virtual;
    Procedure   setPosition(aValue:Integer);virtual;
    Procedure   setPositionNoCalc(aValue:Integer);virtual;
    procedure   InitializeObject; override;
    procedure   FinalizeObject; override;
    function    calcSizeOfHandle:Integer;
    function    PositionToPixelOffset(aPosition:Integer):Integer;
    function    PixelOffsetToPosition(aPxPos:Integer):Integer;
    Procedure   Recalculate;virtual;abstract;
    function    getArea:Integer;virtual;abstract;
  public
    class function supportAdjustment:Boolean;override;
    Property    MinButton:TW3ScrollbarLowerBtn read FUpBtn;
    property    MaxButton:TW3ScrollbarHigherBtn read FDownBtn;
    Property    DragHandle:TW3ScrollbarHandle read FHandle;
  published
    Property    Total:Integer read FTotal write setTotal;
    Property    PageSize:Integer read FPageSize write setPageSize;
    Property    Position:Integer read FPosition write setPosition;
  End;

Now you might be wondering, why do i bother declaring customcontrols that will, after all, be hidden inside the new control? Because that means that you can style them. Smart automatically maps your classnames to the styles in your stylesheet. So if you define a CSS class called TW3ScrollbarLowerBtn, it will be automatically applied to that control. This means you can alter the scrollbars with your own global theme if you have some css skills.

Next, we have the implementation for our baseclass, which couldnt be simpler:

  //###########################################################################
  // TW3CustomScrollBar
  //###########################################################################

  procedure TW3CustomScrollBar.InitializeObject;
  Begin
    inherited;
    FUpBtn:=TW3ScrollbarLowerBtn.Create(self);
    FDownBtn:=TW3ScrollbarHigherBtn.Create(self);
    FHandle:=TW3ScrollbarHandle.Create(self);
  end;

  procedure TW3CustomScrollBar.FinalizeObject;
  Begin
    FUpBtn.free;
    FDownBtn.free;
    FHandle.free;
    inherited;
  end;

  class function TW3CustomScrollBar.supportAdjustment:Boolean;
  Begin
    result:=true;
  end;

  Procedure TW3CustomScrollBar.setTotal(aValue:Integer);
  Begin
    aValue:=TInteger.EnsureRange(aValue,0,MAX_INT);
    if aValue<>FTotal then
    Begin
      Ftotal:=aValue;

      if FPageSize>FTotal then
      FPageSize:=FTotal;

      if FPosition>FTotal-FPageSize then
      Begin
        if (FTotal-FPageSize)<1 then
        FPosition:=0 else
        FPosition:=FTotal-FPageSize;
      end;
      ReCalculate;
      LayoutChildren;
    end;
  end;

  procedure TW3CustomScrollBar.setPageSize(aValue:Integer);
  Begin
    aValue:=TInteger.EnsureRange(aValue,0,FTotal);
    if aValue<>FPageSize then
    Begin
      FPageSize:=aValue;
      if FTotal>0 then
      Begin
        ReCalculate;
        LayoutChildren;
      end;
    end;
  end;

  Procedure TW3CustomScrollBar.setPosition(aValue:Integer);
  Begin
    aValue:=TInteger.EnsureRange(aValue,0,FTotal-FPageSize);
    if aValue<>FPosition then
    Begin
      FPosition:=aValue;
      if FTotal>0 then
      Begin
        ReCalculate;
        LayoutChildren;
      end;
    end;
  end;

  Procedure TW3CustomScrollBar.setPositionNoCalc(aValue:Integer);
  Begin
    aValue:=TInteger.EnsureRange(aValue,0,FTotal-FPageSize);
    if aValue<>FPosition then
    FPosition:=aValue;
  end;

  function TW3CustomScrollBar.calcSizeOfHandle:Integer;
  var
    mTemp:  Integer;
  Begin
    mTemp:=TInteger.PercentOfValue(PageSize,Total);
    result:=round( mTemp * getArea / 100);
  end;

  function TW3CustomScrollBar.PositionToPixelOffset(aPosition:Integer):Integer;
  var
    mTemp:  Integer;
  Begin
    mTemp:=TInteger.PercentOfValue(aPosition,Total);
    result:=round( mTemp * getArea / 100);
  end;

  function TW3CustomScrollBar.PixelOffsetToPosition(aPxPos:Integer):Integer;
  var
    mTemp: Integer;
  Begin
    mTemp:=TInteger.PercentOfValue(aPxPos,getarea);
    result:=trunc( (mTemp * Total) / 100 );
  end;

The vertical bar

Deriving from this skelleton class we can now easily derive both horizontal and vertical scrollbars. Let’s start with the vertical. This one is a bit more complex since we need to dig into javascript events directly. I did this not to hijack the published events (like mousedown etc) making sure these can still be used. Here is the interface

  TW3VerticalScrollbar = Class(TW3CustomScrollBar)
  private
    FDragSize:  Integer;
    FDragPos:   Integer;
    FMoving:    Boolean;
    FEntry:     Integer;

    procedure   jsmousedown(eventObj:JMouseEvent);
    procedure   jsmousemove(eventObj:JMouseEvent);
    procedure   jsmouseup(eventObj:JMouseEvent);

    Procedure   doMouseDown(button:TMouseButton;
                shiftState:TShiftState;x,y:Integer);
    procedure   doMouseUp(button:TMouseButton;
                shiftState:TShiftState;x,y:Integer);
    procedure   doMouseMove(shiftState:TShiftState;x,y:Integer);
  protected
    procedure InitializeObject; override;
    procedure Resize;Override;
    function  getArea:Integer;override;
    Procedure Recalculate;override;
  End;

And here is the implementation. Never mind the colors, I havent done the CSS yet 🙂


  procedure TW3VerticalScrollbar.InitializeObject;
  Begin
    inherited;
    (* minbutton.color:=clGreen;
    maxButton.color:=clCyan;
    draghandle.Color:=clRed; *)

    (* Avoid using up the exposed event handlers *)
    handle.addEventListener('mousedown',@jsmousedown,false);
    handle.addEventListener('mousemove',@jsmousemove,false);
    handle.addEventListener('mouseup',@jsmouseup,false);
  end;

  procedure TW3VerticalScrollbar.jsmousedown(eventObj:JMouseEvent);
  Begin
    eventObj.preventDefault();
    var sr := ScreenRect;
    var shiftState := TShiftState.Current;
    shiftState.MouseButtons := shiftState.MouseButtons or (1 shl eventObj.button);
    shiftState.MouseEvent := eventObj;
    doMouseDown(eventObj.button, shiftState,
             eventObj.clientX-sr.Left, eventObj.clientY-sr.Top);
  end;

  procedure TW3VerticalScrollbar.jsmousemove(eventObj:JMouseEvent);
  Begin
    eventObj.preventDefault();
    var sr := ScreenRect;
    var shiftState := TShiftState.Current;
    shiftState.MouseEvent := eventObj;
    doMouseMove(shiftState, eventObj.clientX-sr.Left, eventObj.clientY-sr.Top);
  end;

  procedure TW3VerticalScrollbar.jsmouseup(eventObj:JMouseEvent);
  Begin
    eventObj.preventDefault();
    var sr := ScreenRect;
    var shiftState := TShiftState.Current;
    shiftState.MouseButtons := shiftState.MouseButtons and not (1 shl eventObj.button);
    shiftState.MouseEvent := eventObj;
    doMouseUp(eventObj.button, shiftState,
           eventObj.clientX-sr.Left, eventObj.clientY-sr.Top);
  end;

  function TW3VerticalScrollbar.getArea:Integer;
  Begin
    result:=Height;

    result:=MaxButton.top - minbutton.boundsRect.bottom;
    exit;

    if minButton.Visible then
    dec(result,MinButton.Height);

    if maxButton.Visible then
    dec(result,MaxButton.height);
  end;

  Procedure TW3VerticalScrollbar.doMouseDown(button:TMouseButton;
            shiftState:TShiftState;x,y:Integer);
  Begin
    if button=mbLeft then
    begin
      if  dragHandle.BoundsRect.ContainsPos(x,y) then
      begin
        FEntry:=y - dragHandle.top;
        FMoving:=True;
      end;
    end;
  end;

  procedure TW3VerticalScrollbar.doMouseMove(shiftState:TShiftState;
            x,y:Integer);
  var
    mNewPos:  Integer;
    dy: Integer;
  Begin
    if FMoving then
    Begin
      (* take offset on draghandle into account *)
      dy:=y - FEntry;

      (* position draghandle *)
      draghandle.top:=TInteger.EnsureRange(dy,
        minButton.top + minButton.height,
        maxButton.top - FDragSize);

      (* Update position based on draghandle *)
      mNewPos:=PixelOffsetToPosition(draghandle.top-MinButton.BoundsRect.Bottom);
      setpositionNoCalc(mNewPos);
    end;
  end;

  procedure TW3VerticalScrollbar.doMouseUp(button:TMouseButton;
            shiftState:TShiftState;x,y:Integer);
  Begin
    if FMoving then
    Begin
      FMoving:=False;
      setPosition(PixelOffsetToPosition
      (draghandle.top-MinButton.BoundsRect.Bottom));
    end;
  end;

  procedure TW3VerticalScrollbar.Resize;
  var
    mTop: Integer;
  Begin
    inherited;
    MinButton.SetBounds(0,0,width,width);
    MaxButton.setBounds(0,(height-width),width,width);

    Recalculate;

    mTop:=MinButton.top + minButton.Height + FDragPos;
    DragHandle.SetBounds(2,mTop,width-4,FDragSize + Border.getVSpace);
  end;

  Procedure TW3VerticalScrollbar.Recalculate;
  Begin
    FDragSize:=calcSizeOfHandle;
    FDragPos:=PositionToPixelOffset(Position);
  end;

And voila — we have a scrollbar!

Scrolltastic

Scrolltastic

Not much to look at, so let’s put some skin on this puppy! Paste this into the application CSS file:


.TW3ScrollbarLowerBtn, .TW3ScrollbarHigherBtn {
  border: 2px ridge rgba(0,0,0,0.3);
  background-color: #FFFFFF;
  overflow: hidden;
  border-radius: 25px;
  -webkit-border-radius: 25px;
     -moz-border-radius: 25px;
      -ms-border-radius: 25px;
       -o-border-radius: 25px;
}

.TW3ScrollbarHandle {
  border: 2px ridge rgba(0,0,0,0.3);
  background-color: #FFFFFF;
  overflow: hidden;
  border-radius: 25px;
  -webkit-border-radius: 25px;
     -moz-border-radius: 25px;
      -ms-border-radius: 25px;
       -o-border-radius: 25px;
}

.TW3VerticalScrollbar {
  border: 2px ridge rgba(0,0,0,0.3);
  background-color: #FFFFFF;
  overflow: hidden;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  border-radius: 25px;
  -webkit-border-radius: 25px;
     -moz-border-radius: 25px;
      -ms-border-radius: 25px;
       -o-border-radius: 25px;
}

Now let’s run the example again and we have a much better looking scrollbar 🙂

One skinned puppy

One skinned puppy

Well I’m sure you see where this is going – so I wont bother skinning it any more on this blog, but making user controls that are 100% javascript, no dependencies on the OS or any other tricks, is pretty darn easy. The scrollbars (properly skinned) will be in the next Smart Mobile Studio update — enjoy!

Smart Mobile Studio, creating a toggle switch

February 19, 2013 Leave a comment

As work continues from the release candidate to the final release – we are busy polishing the product, adding missing bits and pieces, tweaking the css and making things better.

One of the latest controls to be added is the classical iPhone toggle-box (on-off switch) that has been lacking from Smart Mobile Studio. So it’s about time we got it in there 🙂

Creating controls

Smart Mobile Studio component writing is actually very simple. It’s much easier than under Delphi – but it involves one aspect that to some Spartans can feel.. well, a bit odd. Namely the fact that you have to take CSS into account. In this short article i’ll post the code for the TW3ToggleSwitch control (which will be in the next hotfix or update before we officially hit the 1.1 mark).

The standard controls so far

The standard controls so far

The CSS code for TW3Switchbox is fairly straight-forward:


/* ##########################################################################
   # TW3ToggleSwitch
   ########################################################################## */

.TW3ToggleSwitch {
  background-color: #FFFFFF;
	border:1px solid #AAA;
	border-radius:6px;
	color:#FFF;
	font-weight:700;
	overflow:hidden;
	box-shadow:0 1px 0 #FFF;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
 }

.TW3ToggleOnLabel {
  border-radius: 6px;
  text-align:center;
	background:#007FEA;
	text-shadow:0 -1px 0 #093B5C;
	box-shadow:0 4px 5px -2px rgba(0,0,0,0.3) inset;
}

.TW3ToggleOffLabel {
  border-radius: 6px;
  text-align:center;
	box-shadow:0 4px 5px -2px rgba(0,0,0,0.3) inset;
}

.TW3ToggleKnob {
  cursor: pointer;
  background-color: #FFFFFF;
	border:1px solid #AAA;
	border-radius:4px;
	color:#FFF;
	font-weight:700;
	overflow:hidden;
	box-shadow:0 4px 0 -2px #F1F1F1 inset, 0 2em 2em -2em #AAA inset, 0 0 2px rgba(0,0,0,.5);
}

.TW3ToggleKnob:hover {
	background:#E5E5E5;
}

If you are wondering why i have divided the toggle-box into 4 parts (the box, the knob, the on/off labels) there is a good reason for this. It means that you can alter the look of the control without us getting involved. If you dont like the way the control looks – then you are free to alter the CSS and make your own style. Freedom baby 😉

And then there is the pascal classes:

  TW3ToggleKnob = Class(TW3CustomControl)
  protected
    procedure InitializeObject; override;
  End;

  TW3ToggleOnLabel = Class(TW3Label)
  public
    class function supportAdjustment:Boolean;override;
  end;

  TW3ToggleOffLabel = Class(TW3Label)
  public
    class function supportAdjustment:Boolean;override;
  end;

  TW3ToggleSwitch = Class(TW3CustomControl)
  private
    FKnob:    TW3ToggleKnob;
    FOnText:  TW3ToggleOnLabel;
    FOffText: TW3ToggleOffLabel;
    Procedure HandleTouch(Sender: TObject; Info: TW3TouchData);
    procedure HandleMouseDown(sender:Tobject;button:TMouseButton;
              shiftState:TShiftState;x,y:Integer);
    function  getChecked:Boolean;
    procedure setChecked(Const aValue:Boolean);
  protected
    procedure InitializeObject; override;
    Procedure FinalizeObject;Override;
    procedure Resize; override;
  public
    Property  Checked:Boolean read getChecked write setChecked;
    Procedure Toggle;
  End;

And ofcourse, the implementation. Note: the methods “supportAdjustment” is not in the current RTL. All in all it controls the way the method AdjustToParentBox affects it’s sub controls. You dont really have to care about that at this point, it’s taken care of.


  //###########################################################################
  // TW3ToggleOnLabel
  //###########################################################################

  class function TW3ToggleOnLabel.supportAdjustment:Boolean;
  Begin
    result:=False;
  end;

  //###########################################################################
  // TW3ToggleOffLabel
  //###########################################################################

  class function TW3ToggleOffLabel.supportAdjustment:Boolean;
  Begin
    result:=False;
  end;

  //###########################################################################
  // TW3ToggleKnob
  //###########################################################################

  procedure TW3ToggleKnob.InitializeObject;
  begin
    inherited;
    w3_setStyle(Handle,w3_CSSPrefix('Transition'),'left .12s');
  end;

  //###########################################################################
  // TW3ToggleSwitch
  //###########################################################################

  procedure TW3ToggleSwitch.InitializeObject;
  begin
    inherited;
    (* Create the "ON" label *)
    FOnText:=TW3ToggleOnLabel.Create(self);
    FOnText.Caption:='ON';
    FOnText.AlignText:=taCenter;
    FOnText.Font.Color:=clWhite;

    (* Create the "OFF" label *)
    FOffText:=TW3ToggleOffLabel.Create(self);
    FOffText.Caption:='OFF';
    FOffText.Font.Color:=clBlack;
    FOffText.AlignText:=taCenter;

    (* Create our leaver knob *)
    FKnob:=TW3ToggleKnob.create(self);

    (* setup internal handlers *)
    self.OnMouseDown:=HandleMouseDown;

    self.OnTouchBegin:=HandleTouch;
  end;

  Procedure TW3ToggleSwitch.FinalizeObject;
  Begin
    FKnob.free;
    FOffText.free;
    FOnText.free;
    inherited;
  end;

  function  TW3ToggleSwitch.getChecked:Boolean;
  Begin
    result:=FKnob.left>0;
  end;

  procedure TW3ToggleSwitch.setChecked(Const aValue:Boolean);
  Begin
    if aValue<>getChecked then
    Toggle;
  end;

  Procedure TW3ToggleSwitch.Toggle;
  Begin
    case getChecked of
    True:   FKnob.Left:=0;
    False:  FKnob.Left:=(width div 2)-8;
    end;
    w3_callback(
      procedure ()
      begin
        if assigned(OnChanged) then
        onChanged(self);
      end,
      300);
  end;

  Procedure TW3ToggleSwitch.HandleTouch(Sender: TObject; Info: TW3TouchData);
  Begin
    Toggle;
  end;

  procedure TW3ToggleSwitch.HandleMouseDown(sender:TObject;
            button:TMouseButton;
            shiftState:TShiftState;
            x, y : Integer);
  Begin
    if button=mbLeft then
    Toggle;
  end;

  procedure TW3ToggleSwitch.Resize;
  var
    mTemp:  Integer;
    wd: Integer;
    hd: Integer;
  Begin
    wd:=width;
    hd:=height;

    if (wd>0) and (hd>0) then
    begin
      mTemp:=(wd div 2);
      if (FKnob.width<>mTemp)
      or (FKnob.height<>hd) then
      FKnob.SetSize(mTemp + 8,hd);

      FOnText.SetBounds(0,0,mTemp,hd);
      FOffText.SetBounds(mTemp,0,mTemp,hd);
    end;
  end;

The magic movement

How exactly did we animate the button? It slides fluently from left to right (and visa versa)? The magic is in this simple line:

w3_setStyle(Handle,w3_CSSPrefix('Transition'),'left .12s');

In this line we tell the browser that it should apply a transition on a css value, in this case the “left” property of the knob control. So whenever you alter the left position of that control, it will apply a 0.12s delay in the movement. Voila — that’s how you create a very simple and smooth scrolling effect (doesn’t get much simpler than that).

You could also apply it to any other css value, like width/height or background color. It’s really simple to create hardware accelerated effects with very little effort under Smart Mobile Studio. Once you have some CSS under your belt – it’s a piece of cake.

Smart Mobile Studio 1.1 RC build 400 “sneak peak”

February 13, 2013 Leave a comment

It’s been two years in the making, 400.000+ lines of Delphi code, and it’s now in the last stages of testing before release. I give you Smart Mobile Studio 1.1.400 RC:

1.1.400

1.1.400

So what’s new?

You will have to wait for the press release to get the full low-down, but since this is my personal blog I’m free to write whatever i want. So what really excites me about this release are the general IDE improvements. We have been so fortunate to have both Primoz and Christian playing around with the codebase – so things like multithreading and background compilation (which is how the IDE extracts information regarding your code) is now faster than ever.

Parameter insight

Parameter insight

In the previous versions one bottleneck was the code-insight feature (code proposal window that pops up while you type). It worked but it was slow and had the unfortunate tendency to pick up information from an earlier compile sequence. So it was not as accurate as we Spartans are used to. Well this has been taken care of and it’s now spot on, extremely fast and uses its own thread to do its thing.

Code insight

Code insight

The same goes for the unit structure tab, which shows a full overview of the current unit including classes, methods, fields and properties. This to was suffering from having to share a symbol dictionary with the code-insight function. Well that is now a thing of the past and both of them now have their own thread and business logic.

Christian decided to go commando and added a very handy feature: macro recording. So we now have some mysterious new buttons just over the unit structure tab (these should be known by Delphi and freepascal users alike):

Boring tasks be gone!

Boring tasks be gone!

With the new background threading in place, handy features like gabelou hints is now available, you can activate that in the preferences dialog and enjoy the hints and parameter insights that brings. And of course – compiler metrics which will give you more detailed insight into how fast the compiler really is:

Gabelous stuff

Gabelous stuff

You will also find it handy to be able to add your own form-factor sizes directly from the IDE. With so many new mobile devices being launched these days – it’s best to avoid hardcoding anything:

Form factors

Form factors

The component palette has also been expanded. We decided to add more tabs and organize the components in groups. Three new components have been added: Steema Teechart (tw3chart), Listbox (Primoz) and a css animated progressbar.

More tabs

More tabs

We also have dependency validation for components now — so whenever you add a control to your design, it will check if the required units are in your source-code, if not: it will add the units directly. So no more having to add the units yourself 🙂

Thats pretty cool!

Thats pretty cool!

And finally, the classbrowser. You can now click on the ancestor class and navigate there directly, you can also double-click on a method and the IDE will open up the unit in the back so you can look at the code. We have also added a couple of new tabs — these will be implemented as we move along, and they will give you some idea of what the final classbrowser is about. This is the place where you (once we get support for packages) can edit your docs and .. well, you get the idea. Much better than documenting in the code which is a nightmare to maintain. But for this release: ancestor navigation, unit access – as requested by many users.

Class browser

Class browser

Compiler

The Stig

The Stig

I wont blow the whistle on all the features but needless to say we have the most evolved object pascal to JavaScript compiler on the planet. In our labs we call Eric “the stig” of Delphi programming (“the stig” is the nickname for the anonymous and brilliant race car driver, as featured on the Top-Gear british television show). Needless to say we got guns: operator overloading, interface expressions, lambdas, class property expressions, pseudo sets .. the list goes on. What is more important is that the generated code is produced faster (much faster), is more efficient and gives you *ALL* the high-level advantages of traditional object pascal — running in the browser under a language that has no concept of neither class nor interface. That is no small feat ladies and gentlemen.

  • VMT based javascript (true OOP)
  • var parameters
  • Initialization / Finalization support
  • Records, nested records, array of records (et al)
  • Classes, inheritance
  • Partial classes
  • class helpers
  • record helpers
  • lambda support
  • operator overloading
  • speed improvements
  • direct JS object access via variants
  • external classes (map JS classes directly)
  • external functions
  • .. for a full low-down on the compiler, buy the smart mobile studio book here

Soon the compiler will have a new switch, to use java script’s native datatypes. One of the hidden gems of JavaScript is that it does have typed data, but most people don’t use them. So you can allocate arrays of UInt32 (unsigned integer, 32 bits) for instance. By taking advantage of typed arrays you get a phenomenal speed boost if you deal with large and complex numbers.

The RTL

Datasnap support directly from javascript, running in a browser near you soon...

Datasnap support directly from javascript, running in a browser near you soon…

Andre Mucche, the ever creative Spartan which provided Smart Mobile Studio with direct Remobjects support, is currently busy porting over datasnap. Yes, you read right: datasnap support. While it wont make it into the release candidate, we hope to have it done for the final release (but no promises, we are only human). The remobjects import wizard have also been updated with the latest remobjects headers. The phonegap units is also updated and completed, webGL is up to date – and we have added more components and expanded the RTL with too much to list here. Way to much.

For those into large numbers, Christian have ported over Halvard Vassbotn‘s unit for that very thing. We called Halvard up and asked of course, which is proper, and he gave us his blessing. Hopefully we will see Halvard joining the Smart Pascal consortium soon 😉

I also started the conversion of CODEF to smart, so you will notice some new additions to TW3Canvas. If you are wondering what CODEF can do for you, check out this demo (use chromium! or safari — mozilla cant handle the speed).

Credits go out to the team: eric, primoz, christian and andre! Cheers guys!

Embedding images in Smart Mobile Studio

February 1, 2013 Comments off

If you have a lot of images (glyphs, sprites, whatever) in either a Smart Mobile game or a demo – you can actually reduce loading time quite dramatically by embedding the images directly in your source.

Here is how you do it

Under the tools menu you will find a menu item called “image converter”. This is a simple wizard that loads in a picture and converts it to source-code. The resulting string is an URL image which can be used by the fromImageURL methods.

Turning an image into code is easy

Turning an image into code is easy

Now simply paste the generated code into your source-unit and load it up with “FImage.loadFromUrl(cnt_imagedata)” and voila 🙂

Here is the chrome logo converted to text:

const CNT_IMAGEDATA ='data:image/png;base64,'+
'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' +
'dgAAAABJRU5ErkJggg==';