Home > OP4JS > Smart Mobile Studio, Creating a TScrollbox

Smart Mobile Studio, Creating a TScrollbox

February 28, 2013 Leave a comment Go to comments

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);
Advertisements
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: