noloh Logo SmallDeveloper Zone
Username:
Password:
remember meforgot password?Login
twitterfacebookirc
plusfolder closePrinciples
plusdocumentWhat is NOLOH?
plusdocumentWhat's so Bad About Markup?
plusdocumentDevelopment and Philosophy
plusfolder closeFeatures
plusdocumentSyntactical Sugars
plusdocumentMultiple Inheritance
plusdocumentBookmarks and NOLOH
plusdocumentUser State Management
plusdocumentSearch Engine Friendly
plusfolder closeGetting Started
plusdocumentPHP and NOLOH Syntax
plusdocumentHello World
plusdocumentConstructors
plusdocumentInstalling NOLOH
plusfolder closeCrash Course
plusdocumentNOLOH and CSS
plusdocumentLayout in NOLOH
plusdocumentDatabases
plusdocumentData::$Links
plusdocumentEvents in NOLOH
plusdocumentMoving and Resizing Your Objects
plusdocumentMultiple Inheritance
plusdocumentBookmarks and NOLOH
plusdocumentData Binding
plusfolder closeAdvanced Topics
plusdocumentCustom Events
plusdocumentClientside Functions
plusfolder closeSyntactic Sugars
plusdocumentSyntactical Sugars
plusdocumentCascading
plusfolder closeCoding Guidelines
plusdocumentBest Practices
plusdocumentNOLOH Naming Conventions
Moving and Resizing Your Objects
Moving and Resizing Your Objectsoverviewdiscussion

Shifts allow you to define how objects will move or resize when an object is dragged. Shifts are very powerful and allow for advanced drag and drop functionality, in addition to other advanced shifting capabilities.

NOLOH allows you to define complex shifts for controls in an easy and intuitive manner. We believe that we allow for some of the most advanced functionality in ways that have not been thought of before. Watch the screencast for an in-depth example.

Adding Shifts

Rather than go into a lengthy explanation, let's jump right into an example:

//Instantiates a button
$button = new Button("Drag Me");
//The following line is all you need to make your object draggable
$button->Shifts[] = Shift::Location($button);

The left part of the statement tells PHP to add to the Shifts ArrayList of the $button object. The object will shift according to the various shift descriptions it has in its Shifts ArrayList.

$button->Shifts[] =

Now, the right part of the statement is a bit more interesting and VERY powerful.

Shift::Location($button);

What this says is that when you drag this button you would like it to shift the location of the button. In our example we used Shift::Location, but you can actually shift any aspect that you like. Let's look at the following possibilities.

//Position
Shift::Left //Shifts the specified object's Left
Shift::Top //Shifts the specified object's Top
Shift::Location //Shifts both the Left and the Top of the specified object
 
//Dimension
Shift::Width //Shifts the specified object's Width
Shift::Height //Shifts the specified object's Height
Shift::Size //Shifts both the Width and the Height of the specified object

The above descriptions mention "specified object"; let us explain that term. The rest of the statement (to the right of the "=") says:

Shift::Location($button);

The above statement specifies which Object you would like to shift. It doesn't have to be the same object that's launching the shifting. In the following example we have a label in addition to our button. You can have an object shift as many other objects as you wish.

//Instantiates a button
$button = new Button("Drag Me");
$label = new Label("Look how I'm shifting");
$button->Shifts[] = Shift::Location($label);

In the above example $button will Shift $label. Thus, $button will stay stationary, and $label will move. But in the following example, we will add a shift so that both $button and $label Shift:

//Instantiates a button
$button = new Button("Drag Me");
$label = new Label("Look how I'm shifting");
//Will shift the Location $button, when $button is dragged.
$button->Shifts[] = Shift::Location($button);
//Will shift the Location $label when $button is dragged.
$button->Shifts[] = Shift::Location($label);

In the above example, we shifted the location of $button, and $label, but we don't have to only shift the location. In the following example, we're going to shift the Location and Size of an object.

//Instantiates a button
$button = new Button("Drag Me");
$label = new Label("Look how I'm shifting");
//Will shift the location $button, when $button is dragged.
$button->Shifts[] = Shift::Location($button);
//Will shift the location of $label when $button is dragged.
$button->Shifts[] = Shift::Location($label);
//Will shift the Width and Height of $label when $button is dragged.
$button->Shifts[] = Shift::Size($label);

Now, when $button is dragged, $button, and $label will move. In addition, while $label is moving, its Width and Height will also change. Remember, you're not bound to only use Location and Size. You can just as easily have specified Width, Height, Left, and Top. If you specify just a Width or Height, or just a Left and Top, then only the corresponding property will Shift.

$button->Shifts[] = Shift::Left($label);

In the above example, $label will only move horizontally, regardless of whatever movements your mouse is making.

More Properties of Shifts

Now that we've covered the basics of shifting, let us now show you how you can control the various ways in which an object will shift. In the following example, we're going to set some properties of the Shift. Please note that all the properties other than the object are optional, and don't need to be set for shifting to work.

$button->Shifts[] = Shift::Location($label, 0, 200, 0, 300, Shift::Normal, 1);

Ok, the above statement might look a little daunting, but it's actually very simple. All shifts allows you to specify constraints. Lets go over the first four: 0, 200, 0, 300. These correspond to minimum left, maximum left, minimum top, maximum top. So in this above example, $label would be not be able to shift to the left of the 0th pixel of its parent container, and not be able to shift right of the 200th pixel of its parent container. It would also not be able to move above the 0th pixel, or below the 300th pixel of its parent container. So, as you can see, we're basically setting the bounds. If none are set, then it's not bound.

Let's get into the next two properties:

Shift::Normal means that when your object is shifting, it will display normally. The other option is to Shift::Ghost, which will create a transparent copy of the object that will shift while the original object remains in place. This is useful for many drag-and-drop cases when a degree of validation is required before actual changes in position take place.

Now, the last property is the ratio of pixels that the object will move to the pixels that your mouse moves. By default, the ratio is 1 which means the object will shift one to one with the mouse cursor. But, you could also set this ratio to -1, 2, etc. Thus enabling you to control how fast you would like things to shift, or whether you want them to shift in an opposite direction.

Let us quickly provide a run-down of the properties for the various Shifts:

//Shifts only the Left
Shift::Left($control, $minLeft, $maxLeft, $type, $ratio)
//Shifts only the Top
Shift::Top($control, $minTop, $maxTop, $type, $ratio)
//Shifts both the Left and Top
Shift::Location($control, $minLeft, $maxLeft, $minTop, $maxTop, $type, $ratio)
//Shifts only the Width
Shift::Width($control, $minWidth, $maxWidth, $type, $ratio)
//Shifts only the Height
Shift::Height($control, $minHeight, $maxHeight, $type, $ratio)
//Shifts both the Width and Height
Shift::Size($control, $minWidth, $maxWidth, $minHeight, $maxHeight, $type, $ratio)

Shifts::With

Shifts::With allows for a control to Shift when another object shifts. Like Shift, Shifts::With is just as easy to implement. Rather than having an initial object needing to know everything it's going to shift, you can simply tell a control what you want it to shift with. This is pretty powerful when you think about the implications of it.

Ok, let's get into an example:

//Will shift the Location $button, when $button is dragged.
$button->Shifts[] = Shift::Location($button);
/*Ok, so what the following line says is that $label should
shift its location when $button is shifted.*/
$label->Shifts[] = Shift::With($button, Shift::Location);
 
Ok, so rather than having $button specifying that it will shift $label, you can just tell have $label specify what it's going to shift with, and how it will shift. Here is a dynamic example that really brings the point home:
//...
 
//Let's look carefully at this loop, assume that Controls is empty.
$left = 0;
for($i=0; $i<10; ++$i)
{
    $but = &new Button("Drag me $i", $left);
    //If this is the first run of the loop, then $but will shift with $button
    if($i == 0)
        $but->Shifts[] = Shift::Location($but);
    else
    {
        /*If this is not the first time, we're telling $but to shift with the
        previous $but.*/
        $but->Shifts[] = Shift::With($this->Controls[$i-1], Shift::Left);
    }
    //Add $but to the Controls ArrayList of this container
    $this->Controls->Add($but);
    $left+=100;
}
 
//...

In the above example, we dynamically chained several buttons to shift when the previous button shifts. Rather than having to the first $but shift each individual button, one can easily make a modification to allow for $but to also shift itself, thus allowing for even more complex chaining. Instead of a situation where you would have to have each button shift the rest when it's dragged, you can simply add a normal Shift to each $but. Thus, when any of the $but's are dragged, all the buttons to the right of it move too.

class Example extends Panel
{
    function Example()
    {
        parent::Panel();
        // Creates a button
        $firstButton = new Button("Drag me");
        // This button will drag itself
        $firstButton->Shifts[] = Shift::Location($firstButton);
        // Adds this button to the Controls ArrayList
        $this->Controls->Add($firstButton);
        // Let's look carefully at this loop
        for($i=1; $i<10; ++$i)
        {
            // Creates button, $but, away from earlier buttons
            $but = &new Button("Drag with", $i * 100);
            // We're telling $but to shift with the previous button
            $but->Shifts[] = Shift::With($this->Controls[$i], Shift::Left);
            //Add $but to the Controls ArrayList of this container
            $this->Controls->Add($but);
        }
    }
}

In the above example, we dynamically chained several buttons to shift when the previous button shifts. Rather than having $firstButton shift each individual button, one can easily make a modification to allow for $but to also shift itself, thus allowing for even more complex chaining. Instead of a situation where you would have to have each button shift the rest when it's dragged, you can simply add a normal Shift to each $but. Thus, when any of the $but's are dragged, all the buttons to the right of it move too. Now that we've gone over the basics of Shifts::With, let's go into the constraints.

$but->Shifts[] = Shift::With($this->Controls[$i-1], Shift::Left, Shift::Mirror);
In the above line, we see Shift::Mirror. This parameter specifies when you want the object to shift with the other object. Shift::Mirror means that it will shift whenever the object is being shifted in a way that corresponds to what you're shifting. For instance, if the object's left is being shifted, you will then shift. But if its height is being shifted, then you will not shift with it. You can specify any Shift to Shift::With. So if you passed in Shift::Height, your object's left will only shift when the object your shifting with height is shifted. This provides for fine grained control of Shifting, and ensure that you won't just shift with every shift, only shifts that make sense.

Drag And Drop

Like everything else in NOLOH, implementing Drag and Drop functionality is really straightforward. Every Control has a DragCatch property which can be set to an Event. Once this is done, whenever a user finishes shifting over the Control with the DragCatch Event, the Event will automatically launch. Furthermore, the developer can access the static variable Event::$Caught to receive an array of objects that were caught by the event. Note that Event::$Caught is always an array, even if one only one object is caught.

Let's see an example:

class Example extends WebPage
{
    function Example()
    {
        parent::WebPage("Drag and Drop Example");
        // Instantiates and Adds a Label that will serve as the object being dragged
        $this->Controls->Add($dragLabel = new Label("Drag Me"));
        // Allow it to be draggable in Ghost mode
        $dragLabel->Shifts[] = Shift::Location($dragLabel, null, null, null, null, Shift::Ghost);
        // Instantiates and Adds a Label that will serve as the object catching the drag
        $this->Controls->Add($catcherLabel = new Label("To Here", 100, 100));
        // Give it a DragCatch Event and pass itself in as a parameter
        $catcherLabel->DragCatch = new ServerEvent($this, "ChangeText", $catcherLabel);
    }
    function ChangeText($catcherLabel)
    {
        /* Give the catcher Label the same Text as the Label being dragged. Note that since only one
        Label is being dragged in this example, it will always be the first index of the Caught array. */
        $catcherLabel->Text = Event::$Caught[0]->Text;
    }
}

What the above example does is create two Labels, one that is draggable across the screen with a Text of "Drag Me" and the other that has a DragCatch Event and a Text of "To Here." When the first Label is dropped over the second, the second Label's Text will change to that of the first, i.e., "Drag Me".

Removing Shift

Removing Shifts works much like you would remove anything from an ArrayList, except that the Remove only considers the type of Shift and the object being shifted. It is unnecessary to pass in bounds a second time. Let's see this in action:

// Lets $dragLabel drag itself within certain bounds.
$dragLabel->Shifts[] = Shift::Location($dragLabel, 100, 500, 100, 500, Shift::Ghost);
// Removes that Shift, so it will no longer be draggable.
$dragLabel->Shifts->Remove(Shift::Location($dragLabel));

But you can also remove just certain sections of the Shift:

// Lets $dragLabel drag itself within certain bounds.
$dragLabel->Shifts[] = Shift::Location($dragLabel, 100, 500, 100, 500, Shift::Ghost);
// Removes the Shift::Left part of that Shift, so what is left is a Shift::Top. Hence, it will draggable only vertically.
$dragLabel->Shifts->Remove(Shift::Left($dragLabel));

And you can also "overkill" your remove:

// Lets $dragLabel drag itself vertically within certain bounds.
$dragLabel->Shifts[] = Shift::Left($dragLabel, 100, 500, 100, 500, Shift::Ghost);
// Removes that Shift, so it will no longer be draggable.
$dragLabel->Shifts->Remove(Shift::Location($dragLabel));

That's all there is to it.

smallarrow
explanation arrowtool tip
2
handlebgexpand left
Right Up Outer CornerRight Down Outer CornerLeft Up Outer CornerLeft Down Outer Cornersearch-bottomclassconstantpropertymethodarticle
controltabsearchbig