×
Namespaces

Variants
Actions
(Difference between revisions)

StarMenu: custom QML component plugin

From Nokia Developer Wiki
Jump to: navigation, search
lildeimos (Talk | contribs)
(Lildeimos -)
hamishwillee (Talk | contribs)
m (Hamishwillee - Change to use new video player which works with Lumia 920 and other mobile browsers)
(41 intermediate revisions by 2 users not shown)
Line 1: Line 1:
[[Category:UI]][[Category:Plugins]][[Category:Qt Quick]][[Category:Code Snippet]][[Category:MeeGo]][[Category:Symbian]]
+
[[Category:UI]][[Category:Plugins]][[Category:Qt Quick]][[Category:Code Snippet]][[Category:MeeGo Harmattan]][[Category:Symbian]]
 
{{Abstract|This article introduces {{Icode|StarMenu}}, a QML pop up menu. }}
 
{{Abstract|This article introduces {{Icode|StarMenu}}, a QML pop up menu. }}
 
{{ArticleMetaData
 
{{ArticleMetaData
|sourcecode= <!-- Link to example source code e.g. [[Media:The Code Example ZIP.zip]] -->
+
|sourcecode= [https://projects.developer.nokia.com/starmenu starmenu] (Nokia Developer Project)
|installfile= <!-- Link to installation file (e.g. [[Media:The Installation File.sis]]) -->
+
|installfile= [http://projects.developer.nokia.com/starmenu/downloads/12 starmenudemo-v1.2.sis] [http://projects.developer.nokia.com/starmenu/downloads/11 starmenudemo_1.2.0_armel.deb]
 
|devices=Nokia C7-00, Nokia N900, Nokia N950, Galaxy tab 7310
 
|devices=Nokia C7-00, Nokia N900, Nokia N950, Galaxy tab 7310
 
|sdk= Nokia Qt SDK 1.1.4
 
|sdk= Nokia Qt SDK 1.1.4
Line 22: Line 22:
  
 
== Introduction ==
 
== Introduction ==
The {{Icode|StarMenu}} is a pop up menu that can be raised by clicking or tapping on an area defined like using {{Icode|MouseArea}} component. The {{Icode|StarMenu}}'s menu items are defined using {{Icode|StarItems}}. This plugin is been developed with Qt 4.7.4 and tested on linux, Nokia N900, Nokia C7-00,  Nokia N950 and Android Galaxy tab GT-7310 (with [https://sourceforge.net/p/necessitas/home/necessitas/ Necesistas] ).
+
The {{Icode|StarMenu}} is a QML contextual pop up menu that can be launched by clicking or tapping on a component like with {{Icode|MouseArea}} element. The {{Icode|StarMenu}}'s menu items are defined using {{Icode|StarItems}}.  
 +
This plugin was developed with Qt 4.7.4 and tested on linux, windows, Nokia N900, Nokia C7-00,  Nokia N950 and Android Galaxy tab GT-7310 (with [https://sourceforge.net/p/necessitas/home/necessitas/ Necesistas] ).
  
== Usage ==
+
[[File:StarMenu_two_starsubmenu.jpg|x300px|two sub menus]]
  
'''Note for Harmattan:'''
+
<mediaplayer>http://www.youtube.com/watch?v=6zlcsgnsTQc</mediaplayer>
.pro file must contains this:
+
  
<code java>
+
== Usage ==
contains(MEEGO_EDITION,harmattan) {
+
{{Note|The documentation to install and use the plugin is in [http://projects.developer.nokia.com/starmenu/wiki the project wiki page].}}
DEFINES += MEEGO_EDITION_HARMATTAN
+
QT += dbus
+
}
+
</code>
+
  
'''To compile and install the plugin, just do:'''
+
{{Icode|StarMenu}} is hidden by default and opens in response to a user action. The purpose of {{Icode|StarMenu}} is to manage all {{Icode|StarItem}} childs. By default they are arrange in a circle shape and, in the center of it, it is painted a star polygon shape with as many spikes as the number of StarItems. It can be visible or not by setting the boolean {{Icode|starCenterVisible}} property.
<code java>
+
The circle shape amplitude is given by {{Icode|radiusH}} and {{Icode|radiusV}} properties.
qmake
+
make
+
make install
+
</code>
+
  
then in your .qml you will need to
+
Clicking on the center of the current menu, will close it and goes back to parent.
<code java>
+
import com.starMenu 1.0
+
</code>
+
  
'''To compile within your project:'''
+
It's possible to click on the center of the first menu to close all.
copy staritem.* and starmenu.* in your project directory and add them to the .pro file.
+
Then in the main.cpp include the headers:
+
<code java>
+
#include "starmenu.h"
+
#include "staritem.h"
+
</code>
+
  
and before setSource() or setMainQmlFile() register the component with:
+
{{Icode|visualParent}} property is used to bind the close menu action to a specified item, so, instead of clicking on center of {{Icode|StarMenu}}, it's possible to set {{Icode|visualParent}} to the main window and close menu everywhere on the screen.
  
<code java>
+
When using {{Icode|visualParent}}, it come handy the {{Icode|color}} property to set a transparent color to the clickable area to close the menu.
qmlRegisterType<StarMenu>("StarMenu", 1, 0, "StarMenu");
+
Changing {{Icode|StarItem visible}} property, makes all {{Icode|StarItem}}s position recalculated with only visible items.  
qmlRegisterType<StarItem>("StarMenu", 1, 0, "StarItem");
+
</code>
+
 
+
then, in your .qml file, you will be able to:
+
<code java>
+
import StarMenu 1.0
+
</code>
+
 
+
 
+
[[File:StarMenu_two_starsubmenu.jpg|x220px|two sub menus]]
+
 
+
The {{Icode|StarMenu}} component displays a contextual menu in a declarative user interface.
+
 
+
{{Icode|StarMenu}} is hidden by default and opens in response to a user action. The purpose of {{Icode|StarMenu}} is to manage all {{Icode|StarItem}} childs. By default they are arrange in a circle shape and, in the center of it, it is painted a star polygon shape with as many spikes as the number of StarItems. It can be visible or not by setting the boolean {{Icode|starCenterVisible}} property.
+
The circle shape amplitude is given by {{Icode|radiusH} and {{Icode|radiusV} properties.
+
Clicking on the center of the current menu, will close it and goes back to parent.
+
It's possible to click on the center of the first menu to close all.
+
visualParent property is used to bind the close menu action to a specified item, so, instead of clicking on center of {{Icode|StarMenu}, it's possible to set {{Icode|visualParent} to the main window and close menu everywhere on the screen.
+
When using {{Icode|visualParent}, it come handy the {{Icode|color} property to set a transparent color to the clickable area to close the menu.
+
Changing {{Icode|StarItem visible}} property, makes all {{Icode|StarItem}s position recalculated with only visible items.  
+
  
  
Line 87: Line 50:
 
   anchors.fill: parent
 
   anchors.fill: parent
 
   radius: 130
 
   radius: 130
  Component.onCompleted: starMenu.rootMenu = true;
+
 
 
   StarItem {
 
   StarItem {
 
     width: 64; height: 64
 
     width: 64; height: 64
Line 142: Line 105:
 
[[File:StarMenu_shapes.jpg|x220px|other shapes]]  
 
[[File:StarMenu_shapes.jpg|x220px|other shapes]]  
  
{{Icode|StarItems}}s can be arranged in a {{Icode|spiral shape}}, in a {{Icode|grid shape}} or in a {{Icode|line shape}}.  
+
{{Icode|StarItems}} can be arranged in a {{Icode|spiral shape}}, in a {{Icode|grid shape}} or in a {{Icode|line shape}}.  
 
{{Icode|StarMenu}} {{Icode|shape}} property could have the following values:  
 
{{Icode|StarMenu}} {{Icode|shape}} property could have the following values:  
  
Line 150: Line 113:
 
* {{Icode|StarMenu.ShapeLine}}
 
* {{Icode|StarMenu.ShapeLine}}
  
 +
Rows in grid shape are arranged centered by the mouse click and are spaced by {{Icode|spacingH}} and {{Icode|spacingV}} properties with columns count defined by {{Icode|columns}} property. Spiral shape takes care of {{Icode|startingRadius}} value to start drawing StarItems and {{Icode|radiusIncrement}} property to shape the spiral. Line shape has a {{Icode|startingAngle}}, {{Icode|radiusIncrement}} and {{Icode|startingRadius}} properties.
  
Rows in grid shape are arranged centered by the mouse click and are spaced by {{Icode|spacingH}} and {{Icode|spacingV}} properties with columns count defined by {{Icode|columns} property. Spiral shape takes care of {{Icode|startingRadius}} value to start drawing StarItems and {{Icode|radiusIncrement}} property to shape the spiral. Line shape has a {{Icode|startingAngle}}, {{Icode|radiusIncrement}} and {{Icode|startingRadius}} properties.
+
StarMenu has the center where user clicks. This center can be defined everywhere in scene coordinates by setting {{Icode|center}} property.
  
StarMenu has the center where user clicks. This centerproperty can be defined everywhere in scene coordinates by setting {{Icode|center}} property.
+
<mediaplayer>http://www.youtube.com/watch?v=Z54zgOod0P0</mediaplayer>
  
{{#ev:youtube|Z54zgOod0P0}}
+
== Examples ==
 +
Here some examples which you can find in the source code of [http://projects.developer.nokia.com/starmenu/wiki#Releasedownloads starmenudemo] in the [http://projects.developer.nokia.com/starmenu/wiki project wiki page]. There are also other useful links like [http://projects.developer.nokia.com/starmenu/wiki/Getting%20started Getting started], [http://projects.developer.nokia.com/starmenu/wiki/Overview Overview] and a developer [http://projects.developer.nokia.com/starmenu/wiki/Components documentation].
  
== Properties & signals ==
+
=== '''How to make a drop down menu''' ===
 +
This is the example number 9 (Menu9.qml) in [http://projects.developer.nokia.com/starmenu/wiki#Releasedownloads starmenudemo sources]. It will explain how to make a drop down menu with {{Icode|StarMenu}} plugin.
  
=== '''StarMenu''' ===
+
[[File:dropDown menu example.jpg|drop down menu example]]
  
'''Properties'''
+
Lets start with a {{Icode|Rectangle}} component with {{Icode|StarMenu}} as a child:
  
* {{Icode|center}}: point
+
<code java>
''Center coordinates relative to the root scene.''
+
Rectagle {
* {{Icode|color}}: color
+
    id: mainButton
''Color of the sensible area to be clicked to close the menu. Useful if {{Icode|visualParent}} is defined.''
+
    property int itemsW: 100
* {{Icode|columns}}: int
+
    property int itemsH: 36
''Columns when {{Icode|ShapeGrid}} is used.''
+
    width: 150; height: 30
* {{Icode|delayChangePos}}: int
+
''Delay between each StarItems positioning after the mouse click. If {{Icode|delayChangePos}} property of StarItem has priority over this.''
+
* {{Icode|open}}: bool
+
''Set or get open state of StarMenu. The value is true only when the StarMenu is the current. Every parents and childs StarMenu have this property set to false. Usually the StarMenu is opened by user action.''
+
* {{Icode|radiusH}}: qreal
+
''Horizontal radius of the circle shape.''
+
* {{Icode|radiusV}}: qreal
+
''Vertical radius of the circle shape.''
+
* {{Icode|rotation}}: qreal
+
''Rotation of StarItems. Only available with circle and spiral shapes.''
+
* {{Icode|radiusIncrement}}: qreal
+
''Used with spiral and line shape to define spacing betweeen StarItems.''
+
* {{Icode|shape}}: enumeration
+
''Shape to be used. The default is ShapeCircle.''
+
  
     * StarMenu.ShapeCircle
+
     StarMenu {
    * StarMenu.ShapeGrid
+
        anchors.fill: parent
    * StarMenu.ShapeSpiral
+
        starCenterVisible: false          // don't display the star polygon
    * StarMenu.ShapeLine
+
        shape: StarMenu.ShapeLine   // define the shape that entries will assume
* {{Icode|spacingH}}: qreal
+
        visualParent: mainWindow    // set the sensible area to the root scene item
''Used with {{Icode|ShapeGrid}} to space horizontally StarItems.''
+
        color: Qt.rgba(0,0,0,0.6)        // set the color of the sensible area
* {{Icode|spacingV}}: qreal
+
        delayChangePos: 150            // entries are arranged with a delay
''Used with {{Icode|ShapeGrid}} to space vertically StarItems.''
+
        radiusIncrement: 0                // the entries are arranded with no offset
* {{Icode|startingAngle}}: qreal
+
        startingAngle: -90                // the line shape direction
''Used with {{Icode|ShapeLine} to define the direction of the StarItems.''
+
        startingRadius: 0                  // offset of the 1st entry
* {{Icode|starCenterVisible}}: bool
+
        center.x: mainButton.x+mainButton.itemsW/2
''Show the star at the center of StarMenu. The star shape has as many spikes as the number of StarItems.''
+
        center.y: mainButton.y+mainButton.height+mainButton.itemsH/2
* {{Icode|startingRadius}}: qreal
+
    }
''Used with ShapeSpiral and with ShapeLine to define the distance from center of the first StarItem.''
+
}
* {{Icode|useParentMenuCenter}}: bool
+
</code>
''When true, the center of the StarMenu will be the center of parent StarMenu if exists.''
+
* {{Icode|visualParent}}: Item
+
''The Item in which the user will click to close the StarMenu. The default sensible area is the parent of StarMenu, with {{Icode|visualParent}, developers are able to redefine this area for example to the main application window.''
+
  
'''Signals'''
+
in this code we start to define {{Icode|itemsW}} and {{Icode|itemsH}} for the dimensions of the menu entries.
 +
{{Icode|StarMenu}} is anchored to {{Icode|mainButton}}, so when it is clicked, the menu will pop up.
 +
A plus to the comments in the above code, the {{Icode|center}} property needs an explaination. When {{Icode|StarMenu}} opens, all entries are placed where the user clicks. This behavior can be changed by setting a value to the {{Icode|center}} property. In this case, we want to rise the menu just under {{Icode|mainButton}}. Since this center is also the center of the 1st item, we calculate the x position to be aligned to the left of {{Icode|mainButton}} and {{Icode|y}} position to be at the bottom of {{Icode|mainbutton}} plus the mid height of 1st item.
  
* {{Icode|StarMenu::starMenuOpening()}}
+
Now lets start to add as many {{Icode|StarItems}} as you like:
''Signal for detecting StarMenu opening.''
+
* {{Icode|StarMenu::starMenuClosing()}}
+
''Signal for detecting StarMenu closing.''
+
  
 +
<code java>
 +
StarItem {
 +
    id: firstItem
 +
    width: mainButton.itemsW; height: mainButton.itemsH
 +
    scale: 0.9
 +
    zoomHoverValue: 1
 +
    Behavior on x  { NumberAnimation { easing.amplitude: 0.3; duration: 800; easing.type: Easing.OutBounce } }
 +
    Behavior on y  { NumberAnimation { easing.amplitude: 0.3; duration: 800; easing.type: Easing.OutBounce } }
 +
    Behavior on opacity  { NumberAnimation { duration: 1000 } }
 +
    Behavior on scale    { NumberAnimation { duration: 200 } }
  
=== '''StarItem''' ===
+
    Rectangle {
 +
        anchors.fill: parent
 +
        border { color: "#000000"; width: 1 }
 +
        Text {
 +
            anchors.fill: parent
 +
            verticalAlignment: Text.AlignVCenter
 +
            horizontalAlignment: Text.AlignHCenter
 +
            text: "item 1"
 +
        }
 +
    }
 +
}
 +
</code>
  
'''Properties'''
+
As mentioned before, all menu entries are placed in center before the menu opens. So it's easy to animate the transition to the open state. Also {{Icode|opacity}}, {{Icode|rotation}} and {{Icode|scale} can be animated.
 +
In {{Icode|StarMenu}} component we set the {{Icode|delayChangePos}} to 150 (ms). If we want to override this value for a particular entry, we can just add to this {{Icode|StarItem}} its own {{Icode|delayChangePos}} property.
 +
Another nice feature of StarItems is the {{Icode|zoomHoveValue}} property. In this case, since there is the text that will be distorted with a scale > 1, we started with a {{Icode|scale}} of 0.9. When the mouse is hover the item, it will be scaled to 1 with an animation.
 +
The {{Icode|StarItem}} interaction with the user can be managed by these signals:
 +
<code java>
 +
StarItem::hoverItem()
 +
StarItem::leaveItem()
 +
StarItem::clicked()
 +
</code>
 +
while for {{Icode|StarMenu}} are available these:
 +
<code java>
 +
StarMenu::starMenuOpening()
 +
StarMenu::starMenuClosing()
 +
</code>
  
* {{Icode|zoomHoverValue}}: qreal
+
Now, lets say we want a sub menu when clicking an entry. Just add a {{Icode|StarMenu}} component as a child of this entry:
''Zoom value when mouse enters.''
+
* {{Icode|delayChangePos}}: int
+
''Delay between StarItem is positioned after the mouse click. If this property is set, it will take priority over the same StaMenu property.''
+
  
'''Signals'''
+
<code java>
 +
StarItem {
 +
id: secondItem
 +
[...]
 +
Rectangle {
 +
            [...]
 +
        }
 +
StarMenu {
 +
anchors.fill: parent
 +
                starCenterVisible: false
 +
                shape: StarMenu.ShapeLine
 +
                visualParent: mainWindow
 +
                parentVisible: true
 +
center.x: mainButton.x+mainButton.itemsW+mainButton.itemsW/2
 +
                center.y: secondItem.y+secondItem.height/2
 +
 +
StarItem { ...}
 +
StarItem { ...}
 +
StarItem { ...}
 +
}
 +
}
 +
</code>
  
* {{Icode|StarItem::hoverItem()}}
+
The only thing we should take care for this example, is the {{Icode|center}} property like explained before. Another thing we should consider is the {{Icode|parentVisible}} property. By default when a sub menu is opened, his parent is hidden. With this property set to true, it will stay visible.
''Signal for detecting when mouse is hover.''
+
* {{Icode|StarItem::leaveItem()}}
+
''Signal for detecting when mouse leaves.''
+
* {{Icode|StarItem::clicked()}}
+
''Signal for detecting a mouse click.''
+
  
 +
 +
About the opening action event by user click, this can be overridden by setting {{Icode|open}} property of {{Icode|StarMenu}} to {{Icode|true}}. So i.e. when the application starts, the menu can be already opened without the user click:
 +
<code java>
 +
Component.onCompleted: starMenu.open = true
 +
</code>
 +
 +
=== '''How to make a dynamic menu''' ===
 +
This is the example number 6 (Menu6.qml) in [http://projects.developer.nokia.com/starmenu/wiki#Releasedownloads starmenudemo sources] source. It will explain how to create menu entries dynamically with {{Icode|StarMenu}} plugin.
 +
 +
[[File:Dynamic filled menu example.jpg|600px| dynamic menu example]]
 +
 +
We need at first a [http://doc.qt.nokia.com/4.7/qml-xmllistmodel.html XmlListModel] to get the feed from Flickr:
 +
<code java>
 +
XmlListModel {
 +
    id: modelList
 +
    property string tags
 +
 +
    function commasep(x)
 +
    {
 +
        return x.replace(' ',',');
 +
    }
 +
 +
    query: "/rss/channel/item"
 +
    namespaceDeclarations: "declare namespace media=\"http://search.yahoo.com/mrss/\";"
 +
 +
    XmlRole { name: "url"; query: "media:content/@url/string()" }
 +
 +
    onTagsChanged: {
 +
        if (tags !== "")
 +
            source = "http://api.flickr.com/services/feeds/photos_public.gne?"+(tags ? "tags="+commasep(tags)+"&" : "")+"format=rss2"
 +
    }
 +
 +
    onStatusChanged: {
 +
        if (status === XmlListModel.Ready && count>0) {
 +
            repeater.model = modelList;
 +
            starMenu.open=true;
 +
            starMenu.updateStarItemPos();
 +
        }
 +
    }
 +
}
 +
</code>
 +
 +
Then a [http://doc.qt.nokia.com/4.7/qml-textinput.html TextInput] component to get the user search words to be used as a Flickr image search:
 +
 +
<code java>
 +
Rectangle {
 +
    id: rectangle1
 +
    x: 0; y: 0; width: 200; height: 40
 +
 +
    TextInput {
 +
        id: textEdit
 +
        anchors.fill: parent
 +
        onAccepted: {
 +
            repeater.model = undefined;
 +
            modelList.tags = textEdit.text;
 +
        }
 +
    }
 +
}
 +
</code>
 +
 +
We can now use {{Icode|StarMenu}} with, as child, a [http://doc.qt.nokia.com/4.7/qml-repeater.html Repeater]. With the delegate a {{Icode|StarItem}} and the {{Icode|modelList}} as the model:
 +
 +
<code java>
 +
    StarMenu {
 +
        id: starMenu
 +
 +
        anchors.fill: parent
 +
        visible: open
 +
        visualParent: mainWindow
 +
        color: Qt.rgba(0,0,0, 0.8)
 +
        center.x: mainWindow.width>>1
 +
        center.y: mainWindow.height>>1
 +
        starCenterVisible: false
 +
        delayChangePos: 60
 +
        shape: StarMenu.ShapeGrid
 +
        columns: 8
 +
        spacingH: 10
 +
        spacingV: 25
 +
 +
        Repeater {
 +
            id: repeater
 +
 +
            delegate: StarItem {
 +
                width:  150; height: 200
 +
 +
                Rectangle {
 +
                    anchors.fill: parent
 +
                    color: "#490202"
 +
                    clip: true
 +
                    Image {
 +
                        anchors.top: parent.top
 +
                        width: 150; height: 200
 +
                        fillMode: Image.PreserveAspectFit
 +
                        source: url
 +
                        opacity: 0
 +
                        onStatusChanged: if (status==Image.Ready) opacity = 1
 +
                        Behavior on opacity { NumberAnimation { duration: 5000; easing.type: Easing.OutQuint } }
 +
                    }
 +
                }
 +
            }
 +
        } // Repeater
 +
    }
 +
</code>
 +
 +
When the user will press return key to accept, the model of {{Icode|repeater}} wil be reset and the {{Icode|modelList} will be retrieved from Flickr. If all is gone well and the {{Icode|modelList}} is filled, all the entries of this {{Icode|StarMenu}} will be filled with images and it will open itself (without user interaction).
 +
 +
This menu has a grid shape so the images are shown in a grid with 8 columns, spaced vertically by 25 pixels and horizontally by 10.
 +
The {{Icode|visualParent}} is the {{Icode|mainWindow}}. Doing so, a click outside the entries will close the menu.
 +
 +
With {{Icode|StarMenu}} way, it is easy for example, to add a menu for each image. Inserting a {{Icode|StarMenu} inside the {{Icode|delegate}, it will come handy to pop up a menu with entries like "download", "thumb up", "share" and so on. Maybe with a circle shape kind menu or a drop down menu like in the previous tutorial.
 +
 +
=== '''A simple dock menu bar''' ===
 +
This is the example number 10 (Menu10.qml) in [http://projects.developer.nokia.com/starmenu/wiki#Releasedownloads starmenudemo sources] source.  It will take an overview on how to create a simple dock menu with {{Icode|StarMenu}} plugin.
 +
 +
[[File:SimpleDock.jpg|516px| simple dock menu example]]
 +
 +
Lets start with the main qml file. Iside it put rectangle (button) where the menu will be binded to and the dock's background:
 +
 +
<code java>
 +
import QtQuick 1.1
 +
import StarMenu 1.0
 +
 +
Rectangle {
 +
    id: main
 +
    width: 600
 +
    height: 400
 +
   
 +
    Rectangle {
 +
        id: pressMe
 +
        width: 100
 +
        height: 50
 +
        Text {
 +
            anchors.fill: parent
 +
            text: "press me"
 +
        }
 +
    }
 +
   
 +
    Rectangle {
 +
        id: mainRect
 +
        x: (main.width-width)>>1
 +
        y: main.height-height+radius
 +
        width: 380
 +
        height: 90
 +
        radius: 13
 +
        visible: menu10.menuOpen
 +
       
 +
        gradient: Gradient {
 +
            GradientStop {
 +
                position: 0
 +
                color: Qt.rgba(.1,.1,.1, 0.2)
 +
            }
 +
            GradientStop {
 +
                position: 0.450
 +
                color: Qt.rgba(.3,.3,.3, 0.8)
 +
            }
 +
            GradientStop {
 +
                position: 0.500
 +
                color: Qt.rgba(.8,.8,.8, 0.8)
 +
            }
 +
            GradientStop {
 +
                position: 0.600
 +
                color: Qt.rgba(.5,.5,.5, 1)
 +
            }
 +
        }
 +
    }
 +
}
 +
</code>
 +
 +
{{Icode|main}} is the main view and the background is positioned at bottom center of the main view. It is visible only when the {{Icode|StarMenu}} with id {{Icode|menu10}} is open.
 +
Now create {{Icode|StarMenu}} component:
 +
 +
<code java>
 +
StarMenu {
 +
    id: menu10
 +
    anchors.fill: parent
 +
   
 +
    starCenterVisible: false
 +
    shape: StarMenu.ShapeLine
 +
    startingRadius: -mainRect.width/2+32
 +
    radiusIncrement: 10
 +
    startingAngle: 0
 +
    center.x: mainRect.x + (mainRect.width>>1)
 +
    center.y: mainRect.y + (mainRect.height>>1)-10
 +
   
 +
    function setStartAnimPosition()
 +
    {
 +
        animate1.starty = si1.y;
 +
    }
 +
   
 +
    onCenterChanged: if (open) setStartAnimPosition();
 +
    onOpenChanged: if (open) setStartAnimPosition();
 +
   
 +
    StarItem {
 +
        id: si1; width: 64; height: 64
 +
        onHoverItem: animate1.start()
 +
        onLeaveItem: { animate1.complete();  animate1.stop(); si1.y=animate1.starty; }
 +
        Rectangle { anchors.fill: parent; color: "#ff0000" }
 +
    }
 +
   
 +
    SequentialAnimation {
 +
        id: animate1
 +
        property real starty
 +
        loops: Animation.Infinite
 +
        running: false
 +
        NumberAnimation { target: si1; property: "y"; easing.type: Easing.OutSine; to: animate1.starty-20; duration: 250 }
 +
        NumberAnimation { target: si1; property: "y"; easing.type: Easing.InSine;  to: animate1.starty; duration: 250 }
 +
    }
 +
}
 +
</code>
 +
 +
The {{Icode|StarMenu}} properties are defined to {{Icode|center}} the menu into the background rectangle.
 +
With {{Icode|startingRadius}} the line shape rotation origin is set to the center of the bounding rect of the menu.
 +
With {{Icode|radiusIncrement}} we defined the space between {{Icode|StarItems}} and with {{Icode|startingAngle}} the menu will be horizontal.
 +
When {{Icode|StarMenu}} is open or when the mainRect changes position (the main window resizes), the function {{Icode|setStartAnimPosition()}} is called to initialize the animation position. The {{Icode|StarItem}} will catch {{Icode|onHoverItem}} and {{Icode|onLeaveItem}} signals to start and stop bouncing animation.
 +
It this example the menu has only 1 item with its own bouncing animation. You can add as many {{Icode|StarItems}} as you like with their own animation and maybe use the {{Icode|Drop down menu}} example to add a pop up menu to the dock's items like in the [http://projects.developer.nokia.com/starmenu/wiki#Releasedownloads starmenudemo] app.
  
 
== Downloads ==
 
== Downloads ==
  
Here the home project link. You will find {{Icode|starMenu-plugin.zip}} which is the installable plugin and {{Icode|starmenudemo.zip}} which is the demo without the need to install the plugin. The complete doxygen documentation is in the plugin zip.
+
Below the home project link. You will find sources of the plugin and the demo in the [http://projects.developer.nokia.com/starmenu/wiki#Releasedownloads wiki project] and the git repo in the [http://projects.developer.nokia.com/starmenu/browser Source] tab.
 +
There are aslo a deb package for Nokia N9/950 and a sis package for symbian Anna or Belle.
  
 
[https://projects.developer.nokia.com/starmenu StarMenu project]
 
[https://projects.developer.nokia.com/starmenu StarMenu project]
 +
 +
== Conclusions ==
 +
 +
I will be glad if you find this component helpful and I will greatly appreciate any feedbacks or suggestions to improve it. Feel free to contact me or use the [http://projects.developer.nokia.com/starmenu/discussion discussion] page on the project wiki.

Revision as of 07:40, 30 January 2013

This article introduces StarMenu, a QML pop up menu.

Article Metadata
Code Example
Source file: starmenu (Nokia Developer Project)
Tested with
SDK: Nokia Qt SDK 1.1.4
Devices(s): Nokia C7-00, Nokia N900, Nokia N950, Galaxy tab 7310
Compatibility
Platform(s): Symbian^3 and later, Harmattan, linux, Windows
Symbian
Device(s): all
Article
Keywords: Menu, QDeclarativeItem, StarMenu
Created: lildeimos (18 Dec 2011)
Last edited: hamishwillee (30 Jan 2013)

Contents

Introduction

The StarMenu is a QML contextual pop up menu that can be launched by clicking or tapping on a component like with MouseArea element. The StarMenu's menu items are defined using StarItems. This plugin was developed with Qt 4.7.4 and tested on linux, windows, Nokia N900, Nokia C7-00, Nokia N950 and Android Galaxy tab GT-7310 (with Necesistas ).

two sub menus

The media player is loading...

Usage

Note.pngNote: The documentation to install and use the plugin is in the project wiki page.

StarMenu is hidden by default and opens in response to a user action. The purpose of StarMenu is to manage all StarItem childs. By default they are arrange in a circle shape and, in the center of it, it is painted a star polygon shape with as many spikes as the number of StarItems. It can be visible or not by setting the boolean starCenterVisible property. The circle shape amplitude is given by radiusH and radiusV properties.

Clicking on the center of the current menu, will close it and goes back to parent.

It's possible to click on the center of the first menu to close all.

visualParent property is used to bind the close menu action to a specified item, so, instead of clicking on center of StarMenu, it's possible to set visualParent to the main window and close menu everywhere on the screen.

When using visualParent, it come handy the color property to set a transparent color to the clickable area to close the menu. Changing StarItem visible property, makes all StarItems position recalculated with only visible items.


StarMenu {
id: starMenu
anchors.fill: parent
radius: 130
 
StarItem {
width: 64; height: 64
Image {
anchors.fill: parent
[...]
}
}
StarItem {
[...]
StarMenu {
[...]
}
}
}


rotation scale delayed animation

It is possible to bind animations to StarItems. When a StarMenu is raised, the StarItems circle shape has the center located by the mouse click (or tap) position and their opacity, rotation, x, y property are set to 0. By doing this:

StarItem {
[...]
Behavior on x { NumberAnimation { duration: 1500; easing.type: Easing.OutBounce } }
Behavior on y { NumberAnimation { duration: 1500; easing.type: Easing.OutBounce } }
Behavior on opacity { NumberAnimation { duration: 2200; easing.type: Easing.OutBounce } }

StarItems are animated from center to their final position.

StarMenu has also a delayChangePos property. For example, when it is set to 100, the animation of the second StarItem is started after 100 ms, the third after 200 ms and so on. StarItem has also a delayChangePos property and if it is set, it take priority over the StarMenu delayChangePos property.

entries as components

StarItems can also contain any other component instead Image component used in these examples:

StarItem {
width: 320; height: 240
scale: 0.3
zoomHoverValue: 1
Behavior on scale { NumberAnimation { duration: 500; easing.type: Easing.OutQuad } }
Column {
Button { text: "Hello Qt" }
Switch { }
RadioButton { }
}
}

other shapes

StarItems can be arranged in a spiral shape, in a grid shape or in a line shape. StarMenu shape property could have the following values:

  • StarMenu.ShapeCircle (default value)
  • StarMenu.ShapeGrid
  • StarMenu.ShapeSpiral
  • StarMenu.ShapeLine

Rows in grid shape are arranged centered by the mouse click and are spaced by spacingH and spacingV properties with columns count defined by columns property. Spiral shape takes care of startingRadius value to start drawing StarItems and radiusIncrement property to shape the spiral. Line shape has a startingAngle, radiusIncrement and startingRadius properties.

StarMenu has the center where user clicks. This center can be defined everywhere in scene coordinates by setting center property.

The media player is loading...

Examples

Here some examples which you can find in the source code of starmenudemo in the project wiki page. There are also other useful links like Getting started, Overview and a developer documentation.

How to make a drop down menu

This is the example number 9 (Menu9.qml) in starmenudemo sources. It will explain how to make a drop down menu with StarMenu plugin.

drop down menu example

Lets start with a Rectangle component with StarMenu as a child:

Rectagle {
id: mainButton
property int itemsW: 100
property int itemsH: 36
width: 150; height: 30
 
StarMenu {
anchors.fill: parent
starCenterVisible: false // don't display the star polygon
shape: StarMenu.ShapeLine // define the shape that entries will assume
visualParent: mainWindow // set the sensible area to the root scene item
color: Qt.rgba(0,0,0,0.6) // set the color of the sensible area
delayChangePos: 150 // entries are arranged with a delay
radiusIncrement: 0 // the entries are arranded with no offset
startingAngle: -90 // the line shape direction
startingRadius: 0 // offset of the 1st entry
center.x: mainButton.x+mainButton.itemsW/2
center.y: mainButton.y+mainButton.height+mainButton.itemsH/2
}
}

in this code we start to define itemsW and itemsH for the dimensions of the menu entries. StarMenu is anchored to mainButton, so when it is clicked, the menu will pop up. A plus to the comments in the above code, the center property needs an explaination. When StarMenu opens, all entries are placed where the user clicks. This behavior can be changed by setting a value to the center property. In this case, we want to rise the menu just under mainButton. Since this center is also the center of the 1st item, we calculate the x position to be aligned to the left of mainButton and y position to be at the bottom of mainbutton plus the mid height of 1st item.

Now lets start to add as many StarItems as you like:

StarItem {
id: firstItem
width: mainButton.itemsW; height: mainButton.itemsH
scale: 0.9
zoomHoverValue: 1
Behavior on x { NumberAnimation { easing.amplitude: 0.3; duration: 800; easing.type: Easing.OutBounce } }
Behavior on y { NumberAnimation { easing.amplitude: 0.3; duration: 800; easing.type: Easing.OutBounce } }
Behavior on opacity { NumberAnimation { duration: 1000 } }
Behavior on scale { NumberAnimation { duration: 200 } }
 
Rectangle {
anchors.fill: parent
border { color: "#000000"; width: 1 }
Text {
anchors.fill: parent
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text: "item 1"
}
}
}

As mentioned before, all menu entries are placed in center before the menu opens. So it's easy to animate the transition to the open state. Also opacity, rotation and {{Icode|scale} can be animated. In StarMenu component we set the delayChangePos to 150 (ms). If we want to override this value for a particular entry, we can just add to this StarItem its own delayChangePos property. Another nice feature of StarItems is the zoomHoveValue property. In this case, since there is the text that will be distorted with a scale > 1, we started with a scale of 0.9. When the mouse is hover the item, it will be scaled to 1 with an animation. The StarItem interaction with the user can be managed by these signals:

StarItem::hoverItem()
StarItem::leaveItem()
StarItem::clicked()

while for StarMenu are available these:

StarMenu::starMenuOpening()
StarMenu::starMenuClosing()

Now, lets say we want a sub menu when clicking an entry. Just add a StarMenu component as a child of this entry:

StarItem {
id: secondItem
[...]
Rectangle {
[...]
}
StarMenu {
anchors.fill: parent
starCenterVisible: false
shape: StarMenu.ShapeLine
visualParent: mainWindow
parentVisible: true
center.x: mainButton.x+mainButton.itemsW+mainButton.itemsW/2
center.y: secondItem.y+secondItem.height/2
 
StarItem { ...}
StarItem { ...}
StarItem { ...}
}
}

The only thing we should take care for this example, is the center property like explained before. Another thing we should consider is the parentVisible property. By default when a sub menu is opened, his parent is hidden. With this property set to true, it will stay visible.


About the opening action event by user click, this can be overridden by setting open property of StarMenu to true. So i.e. when the application starts, the menu can be already opened without the user click:

Component.onCompleted: starMenu.open = true

How to make a dynamic menu

This is the example number 6 (Menu6.qml) in starmenudemo sources source. It will explain how to create menu entries dynamically with StarMenu plugin.

dynamic menu example

We need at first a XmlListModel to get the feed from Flickr:

XmlListModel {
id: modelList
property string tags
 
function commasep(x)
{
return x.replace(' ',',');
}
 
query: "/rss/channel/item"
namespaceDeclarations: "declare namespace media=\"http://search.yahoo.com/mrss/\";"
 
XmlRole { name: "url"; query: "media:content/@url/string()" }
 
onTagsChanged: {
if (tags !== "")
source = "http://api.flickr.com/services/feeds/photos_public.gne?"+(tags ? "tags="+commasep(tags)+"&" : "")+"format=rss2"
}
 
onStatusChanged: {
if (status === XmlListModel.Ready && count>0) {
repeater.model = modelList;
starMenu.open=true;
starMenu.updateStarItemPos();
}
}
}

Then a TextInput component to get the user search words to be used as a Flickr image search:

Rectangle {
id: rectangle1
x: 0; y: 0; width: 200; height: 40
 
TextInput {
id: textEdit
anchors.fill: parent
onAccepted: {
repeater.model = undefined;
modelList.tags = textEdit.text;
}
}
}

We can now use StarMenu with, as child, a Repeater. With the delegate a StarItem and the modelList as the model:

    StarMenu {
id: starMenu
 
anchors.fill: parent
visible: open
visualParent: mainWindow
color: Qt.rgba(0,0,0, 0.8)
center.x: mainWindow.width>>1
center.y: mainWindow.height>>1
starCenterVisible: false
delayChangePos: 60
shape: StarMenu.ShapeGrid
columns: 8
spacingH: 10
spacingV: 25
 
Repeater {
id: repeater
 
delegate: StarItem {
width: 150; height: 200
 
Rectangle {
anchors.fill: parent
color: "#490202"
clip: true
Image {
anchors.top: parent.top
width: 150; height: 200
fillMode: Image.PreserveAspectFit
source: url
opacity: 0
onStatusChanged: if (status==Image.Ready) opacity = 1
Behavior on opacity { NumberAnimation { duration: 5000; easing.type: Easing.OutQuint } }
}
}
}
} // Repeater
}

When the user will press return key to accept, the model of repeater wil be reset and the {{Icode|modelList} will be retrieved from Flickr. If all is gone well and the modelList is filled, all the entries of this StarMenu will be filled with images and it will open itself (without user interaction).

This menu has a grid shape so the images are shown in a grid with 8 columns, spaced vertically by 25 pixels and horizontally by 10. The visualParent is the mainWindow. Doing so, a click outside the entries will close the menu.

With StarMenu way, it is easy for example, to add a menu for each image. Inserting a {{Icode|StarMenu} inside the {{Icode|delegate}, it will come handy to pop up a menu with entries like "download", "thumb up", "share" and so on. Maybe with a circle shape kind menu or a drop down menu like in the previous tutorial.

A simple dock menu bar

This is the example number 10 (Menu10.qml) in starmenudemo sources source. It will take an overview on how to create a simple dock menu with StarMenu plugin.

simple dock menu example

Lets start with the main qml file. Iside it put rectangle (button) where the menu will be binded to and the dock's background:

import QtQuick 1.1
import StarMenu 1.0
 
Rectangle {
id: main
width: 600
height: 400
 
Rectangle {
id: pressMe
width: 100
height: 50
Text {
anchors.fill: parent
text: "press me"
}
}
 
Rectangle {
id: mainRect
x: (main.width-width)>>1
y: main.height-height+radius
width: 380
height: 90
radius: 13
visible: menu10.menuOpen
 
gradient: Gradient {
GradientStop {
position: 0
color: Qt.rgba(.1,.1,.1, 0.2)
}
GradientStop {
position: 0.450
color: Qt.rgba(.3,.3,.3, 0.8)
}
GradientStop {
position: 0.500
color: Qt.rgba(.8,.8,.8, 0.8)
}
GradientStop {
position: 0.600
color: Qt.rgba(.5,.5,.5, 1)
}
}
}
}

main is the main view and the background is positioned at bottom center of the main view. It is visible only when the StarMenu with id menu10 is open. Now create StarMenu component:

StarMenu {
id: menu10
anchors.fill: parent
 
starCenterVisible: false
shape: StarMenu.ShapeLine
startingRadius: -mainRect.width/2+32
radiusIncrement: 10
startingAngle: 0
center.x: mainRect.x + (mainRect.width>>1)
center.y: mainRect.y + (mainRect.height>>1)-10
 
function setStartAnimPosition()
{
animate1.starty = si1.y;
}
 
onCenterChanged: if (open) setStartAnimPosition();
onOpenChanged: if (open) setStartAnimPosition();
 
StarItem {
id: si1; width: 64; height: 64
onHoverItem: animate1.start()
onLeaveItem: { animate1.complete(); animate1.stop(); si1.y=animate1.starty; }
Rectangle { anchors.fill: parent; color: "#ff0000" }
}
 
SequentialAnimation {
id: animate1
property real starty
loops: Animation.Infinite
running: false
NumberAnimation { target: si1; property: "y"; easing.type: Easing.OutSine; to: animate1.starty-20; duration: 250 }
NumberAnimation { target: si1; property: "y"; easing.type: Easing.InSine; to: animate1.starty; duration: 250 }
}
}

The StarMenu properties are defined to center the menu into the background rectangle. With startingRadius the line shape rotation origin is set to the center of the bounding rect of the menu. With radiusIncrement we defined the space between StarItems and with startingAngle the menu will be horizontal. When StarMenu is open or when the mainRect changes position (the main window resizes), the function setStartAnimPosition() is called to initialize the animation position. The StarItem will catch onHoverItem and onLeaveItem signals to start and stop bouncing animation. It this example the menu has only 1 item with its own bouncing animation. You can add as many StarItems as you like with their own animation and maybe use the Drop down menu example to add a pop up menu to the dock's items like in the starmenudemo app.

Downloads

Below the home project link. You will find sources of the plugin and the demo in the wiki project and the git repo in the Source tab. There are aslo a deb package for Nokia N9/950 and a sis package for symbian Anna or Belle.

StarMenu project

Conclusions

I will be glad if you find this component helpful and I will greatly appreciate any feedbacks or suggestions to improve it. Feel free to contact me or use the discussion page on the project wiki.

3886 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×