Saturday, January 31, 2015
Creating a Pentomino game using AS3 Part 15
In this tutorial well add the ability to set canvas size in the level editor.
Go to your Flash project and create a new MovieClip based on win_screen. Give the new MC a class path of new_edit_screen. Inside of it we need to include 4 objects at least - two text field inputs tWidth and tHeight (max chars - 2), a button btn_continue and an error message turned into a movie clip with id "incorrect".
Delete it from stage and just keep it in the library. Now return to pentomino_editor.as script file. Inside the constructor, delete all the lines that declare and create the map. Add a listener for btn_reset button and set its click event handler to a function that calls newLevel(). Call newLevel() from the constructor too.
Now create the newLevel() function.
First thing we do here is add an instance of new_edit_screen to the stage.
Add lines that only allow numeric values in tWidth and tHeight, also set their default values:
Set incorrects alpha to 0 (since there was no error yet):
Add a click event listener to btn_continue, set its handler to an internal function editContinue:
Create the editContinue() function inside newLevel(). First thing we do is check if the specified width and height is correct:
If it is correct, we delete the newScreen object from stage, set mapGrid to an empty array and declare width and height variables:
Add two loops that add values to mapGrid based on width and height:
Then calculate grid values and draw the grid:
Full newLevel() function:
Full code so far:
Thanks for reading!
Results:
Read more »
Go to your Flash project and create a new MovieClip based on win_screen. Give the new MC a class path of new_edit_screen. Inside of it we need to include 4 objects at least - two text field inputs tWidth and tHeight (max chars - 2), a button btn_continue and an error message turned into a movie clip with id "incorrect".
Delete it from stage and just keep it in the library. Now return to pentomino_editor.as script file. Inside the constructor, delete all the lines that declare and create the map. Add a listener for btn_reset button and set its click event handler to a function that calls newLevel(). Call newLevel() from the constructor too.
public function pentomino_editor()
{
// add shape buttons
for (var i:int = 0; i < 4; i++) {
for (var u:int = 0; u < 3; u++) {
var shapeButton:MovieClip = new edit_shape();
shapeButton.x = 528 + u * 62;
shapeButton.y = 15 + i * 84;
addChild(shapeButton);
shapeButton.bg.alpha = 0.3;
shapeButton.shape.gotoAndStop(3 * i + u + 1);
shapeButtons.push(shapeButton);
shapeButton.addEventListener(MouseEvent.ROLL_OVER, buttonOver);
shapeButton.addEventListener(MouseEvent.ROLL_OUT, buttonOut);
}
}
// buttons
btn_mainmenu.addEventListener(MouseEvent.CLICK, doMainmenu);
btn_reset.addEventListener(MouseEvent.CLICK, function():void{newLevel()});
// new level
newLevel();
}
Now create the newLevel() function.
First thing we do here is add an instance of new_edit_screen to the stage.
var newScreen:MovieClip = new new_edit_screen();
addChild(newScreen);
Add lines that only allow numeric values in tWidth and tHeight, also set their default values:
newScreen.tWidth.restrict = "0-9";
newScreen.tHeight.restrict = "0-9";
newScreen.tWidth.text = 10;
newScreen.tHeight.text = 6;
Set incorrects alpha to 0 (since there was no error yet):
newScreen.incorrect.alpha = 0;
Add a click event listener to btn_continue, set its handler to an internal function editContinue:
newScreen.btn_continue.addEventListener(MouseEvent.CLICK, editContinue);
Create the editContinue() function inside newLevel(). First thing we do is check if the specified width and height is correct:
if (newScreen.tWidth.text == "" || newScreen.tHeight.text == "" || newScreen.tWidth.text == "0" || newScreen.tHeight.text == "0") {
newScreen.incorrect.alpha = 1;
return;
}
If it is correct, we delete the newScreen object from stage, set mapGrid to an empty array and declare width and height variables:
newScreen.parent.removeChild(newScreen);
mapGrid = [];
var width:int = newScreen.tWidth.text;
var height:int = newScreen.tHeight.text;
Add two loops that add values to mapGrid based on width and height:
for (var i:int = 0; i < height; i++) {
mapGrid[i] = [];
for (var u:int = 0; u < width; u++) {
mapGrid[i][u] = 1;
}
}
Then calculate grid values and draw the grid:
// grid settings
calculateGrid();
addChild(gridShape);
gridShape.x = gridStartX;
gridShape.y = gridStartY;
// draw tiles
drawGrid();
Full newLevel() function:
private function newLevel():void {
var newScreen:MovieClip = new new_edit_screen();
addChild(newScreen);
newScreen.tWidth.restrict = "0-9";
newScreen.tHeight.restrict = "0-9";
newScreen.tWidth.text = 10;
newScreen.tHeight.text = 6;
newScreen.incorrect.alpha = 0;
newScreen.btn_continue.addEventListener(MouseEvent.CLICK, editContinue);
function editContinue(evt:MouseEvent):void {
if (newScreen.tWidth.text == "" || newScreen.tHeight.text == "" || newScreen.tWidth.text == "0" || newScreen.tHeight.text == "0") {
newScreen.incorrect.alpha = 1;
return;
}
newScreen.parent.removeChild(newScreen);
mapGrid = [];
var width:int = newScreen.tWidth.text;
var height:int = newScreen.tHeight.text;
for (var i:int = 0; i < height; i++) {
mapGrid[i] = [];
for (var u:int = 0; u < width; u++) {
mapGrid[i][u] = 1;
}
}
// grid settings
calculateGrid();
addChild(gridShape);
gridShape.x = gridStartX;
gridShape.y = gridStartY;
// draw tiles
drawGrid();
}
}
Full code so far:
package
{
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.sampler.NewObjectSample;
import flash.utils.ByteArray;
/**
* Open-source pentomino game engine
* @author Kirill Poletaev
*/
public class pentomino_editor extends MovieClip
{
private var mapGrid:Array = [];
private var shapeButtons:Array = [];
private var gridShape:Sprite = new Sprite();
private var canPutShape:Sprite = new Sprite();
private var gridStartX:int;
private var gridStartY:int;
private var gridCellWidth:int;
public function pentomino_editor()
{
// add shape buttons
for (var i:int = 0; i < 4; i++) {
for (var u:int = 0; u < 3; u++) {
var shapeButton:MovieClip = new edit_shape();
shapeButton.x = 528 + u * 62;
shapeButton.y = 15 + i * 84;
addChild(shapeButton);
shapeButton.bg.alpha = 0.3;
shapeButton.shape.gotoAndStop(3 * i + u + 1);
shapeButtons.push(shapeButton);
shapeButton.addEventListener(MouseEvent.ROLL_OVER, buttonOver);
shapeButton.addEventListener(MouseEvent.ROLL_OUT, buttonOut);
}
}
// buttons
btn_mainmenu.addEventListener(MouseEvent.CLICK, doMainmenu);
btn_reset.addEventListener(MouseEvent.CLICK, function():void{newLevel()});
// new level
newLevel();
}
private function newLevel():void {
var newScreen:MovieClip = new new_edit_screen();
addChild(newScreen);
newScreen.tWidth.restrict = "0-9";
newScreen.tHeight.restrict = "0-9";
newScreen.tWidth.text = 10;
newScreen.tHeight.text = 6;
newScreen.incorrect.alpha = 0;
newScreen.btn_continue.addEventListener(MouseEvent.CLICK, editContinue);
function editContinue(evt:MouseEvent):void {
if (newScreen.tWidth.text == "" || newScreen.tHeight.text == "" || newScreen.tWidth.text == "0" || newScreen.tHeight.text == "0") {
newScreen.incorrect.alpha = 1;
return;
}
newScreen.parent.removeChild(newScreen);
mapGrid = [];
var width:int = newScreen.tWidth.text;
var height:int = newScreen.tHeight.text;
for (var i:int = 0; i < height; i++) {
mapGrid[i] = [];
for (var u:int = 0; u < width; u++) {
mapGrid[i][u] = 1;
}
}
// grid settings
calculateGrid();
addChild(gridShape);
gridShape.x = gridStartX;
gridShape.y = gridStartY;
// draw tiles
drawGrid();
}
}
private function calculateGrid():void {
var columns:int = mapGrid[0].length;
var rows:int = mapGrid.length;
// free size: 520x460
// fit in: 510x450
// calculate width of a cell:
gridCellWidth = Math.round(510 / columns);
var width:int = columns * gridCellWidth;
var height:int = rows * gridCellWidth;
// calculate side margin
gridStartX = (520 - width) / 2;
if (height < 450) {
gridStartY = (450 - height) / 2;
}
if (height >= 450) {
gridCellWidth = Math.round(450 / rows);
height = rows * gridCellWidth;
width = columns * gridCellWidth;
gridStartY = (460 - height) / 2;
gridStartX = (520 - width) / 2;
}
}
private function drawGrid():void {
gridShape.graphics.clear();
var width:int = mapGrid[0].length;
var height:int = mapGrid.length;
var i:int;
var u:int;
// draw background
for (i = 0; i < height; i++) {
for (u = 0; u < width; u++) {
if (mapGrid[i][u] == 1) drawCell(u, i, 0xffffff, 1, 0x999999);
}
}
}
private function drawCell(width:int, height:int, fill:uint, thick:Number, line:uint):void {
gridShape.graphics.beginFill(fill);
gridShape.graphics.lineStyle(thick, line);
gridShape.graphics.drawRect(width * gridCellWidth, height * gridCellWidth, gridCellWidth, gridCellWidth);
}
private function buttonOver(evt:MouseEvent):void {
evt.currentTarget.bg.alpha = 1;
}
private function buttonOut(evt:MouseEvent):void {
evt.currentTarget.bg.alpha = 0.3;
}
private function doMainmenu(evt:MouseEvent):void {
(root as MovieClip).gotoAndStop(1);
}
}
}
Thanks for reading!
Results:
Barish Me Judai by A Hameed Pdf Free Download
Download Free PDF Book Barish Mein Judai Novel Authored By A Hameed. Barish Main Judai is an interesting novel contains a beautiful social romantic and instructive story in Urdu language. Click on the following links to download. Barish Main Judai complete novel, Download Free PDF Book for your offline reading.
KOCASO K Mini 7 9 inch Tablet PC Firmware
KOCASO K-Mini Allwinner A31S
7.9 inch Android Tablet Firmware
Tablets Recovery , Restore , Upgrade Instructions
Review :
Kocaso K-Mini,7.9 inch android tablet is Quad Core super fast Tablet. K-Mini Tablet deliver high performance graphics without consuming much battery. It has the same thickness as iPad Mini 8.33 cm with 7.9 inch IPS screen adopted iPad mini,Text is razor sharp ,Colors are vibrant. Having very powerful bluetooth 4.0 version to support fast data transfer,connecting audio devices , keyboard ,headset . Kocaso K-Mini comes with one year warranty which cover its hardware warranty as well which make this tablet pc best for buying. Factory installed firmware is Android 4.2
Company Warranty :
One year warranty cover repair or replacement of defective products.
Encyclopedia:-
Read Article About Allwinner Technology
Read Article About Allwinner Technology
Specifications:
LCD | 7.9" IPS Screen |
Screen Resolution | 1024 x 768 Pix |
Processor | upto 1.2 Ghz Quad Core |
Chipset / Boxchip | Allwinner A31S |
RAM | 1GB DDR3 DRAM |
Built in Memory | 8 GB |
External Memory | Support Micro Card (Max 32GB) |
Wifi | 802.11 b/g/n supported |
Blue tooth | 4.0 |
Sim | N/A |
Camera | 0.3 Megapixel front , 2Mp rare cam |
HDMI /3g Dongle | HDMI , Usb 2.0, HDMI (Mini C) ,Support 3G Dongle |
Microphone | Built IN |
Weight | 412 g |
Android Version | 4.2 |
Flashing Tools:
- Tablet Flashing Tool :Firmware upgrade tool LiveSuit & Drivers
- Tablet Flashing Tool: Firmware upgrade Tool Phoenix Usb Pro
- Flashing with TF Card:Firmware update instruction with microSD card
Flashing Tutorials:
- LiveSuit Tutorial : how to flash tablet with LiveSuit
- Phoenix Usb PrO Video Tutorial :Tutorial
Recommended Tools:
You can also use : Android Multi Tools
Common Android Tablets issues :
The following firmware , ROM file will be used when your Android tablet facing various problems .
1. Forgotten Pattern Lock on Android Tablets.
2.Too many pattern attempts / Reset user lock.
3. Tablets PC stuck on Gmail account.
4. Android Tablet PC stuck on Android logo.
5. Tablet Android hang on start-up / Multiple errors generating by OS.
6. Google play store having problems or generating errors.
7.Upgrading to new Android OS.
6. Google play store having problems or generating errors.
7.Upgrading to new Android OS.
you can use this Android Tablet firmware, ROM to restore your Android China tablets to generic firmwares or upgrades . Make sure to charge battery upto 60%. Power failure during flashing may result dead or broken tablets.
Note : Flashing generic tablet firmware should be last option.
Firmware Download
Download Official Firmware
jQuery Touch Screen Effect Image Slider Mouse Press and Move
As the People started using Touch Screen devices, More than half of the Traffic now comes from Touch Screen Devices. It is important to have Image Slider having same effect on Computer screen.
Download Demo view-source
<script type=text/javascript src=http://code.jquery.com/jquery-1.4.2.js></script>
<script type=text/javascript src=http://smoothdivscroll.com/js/jquery-ui-1.8.23.custom.min.js></script>
<script type=text/javascript src=http://smoothdivscroll.com/js/jquery.mousewheel.min.js></script>
<script src="http://smoothdivscroll.com/js/jquery.smoothdivscroll-1.3-min.js"></script>
<script src="http://smoothdivscroll.com/js/jquery.kinetic.js"></script>
<script type="text/javascript">
// Initialize the plugin with no custom options
$(document).ready(function () {
$("#makeMeScrollable").smoothDivScroll({
hotSpotScrolling: false,
touchScrolling: true,
manualContinuousScrolling: true,
mousewheelScrolling: false
});
});
</script>
KirSQLite Flex AIR Database Manager Part 2
In this tutorial well work a little more on the layout - the data grid of the table view screen, specifically.
Firstly, well turn the contents of the first NavigatorContent object into a VGroup, which contains an HBox (something I added just now) and an AdvancedDataGrid that we already have.
The HBox is a container which will contain some tools for editing the data grid. Well add a new column to the datagrid today, which will be a column of CheckBox objects. This way the user will be able to select one or multiple items to perform an action on all of them, for example, delete them all.
For this feature specifically the HBox will contain a CheckBox which will allow the user to select or deselect all of the entries in the table. Set its label to "Select all" and set its change event listener to a function called selectAllChange(), and pass "event" in the parameter. Next to the checkbox, add a button (which does nothing right now) with a label "Delete selected".
In the AdvancedDataGrid itself, well do quite a few changes too. First, set its id to tableGrid. Set its editable property to true.
In the columns array, add a new AdvancedDataGridColumn object with blank headerText and width of 30. Set its sortable, draggable, editable and resizable properties to false. Set this particular columns itemRenderer to an fx:Component container, which contains an mx:Box container, which contains a CheckBox object. Set this CheckBoxs selected property bound to data.sel.
Set the idnum columns editable property to false. Those are all the changes we made to the data grid:
The "sel" property of the "data" object is a boolean variable that is set in the testData array collection. Lets add that to all the items in the array and set the values to false. Lets also increase the number of objects in the array for testing purposes:
Now create fx:Script tags to create a function called selectAllChange(). This function checks if the "Select all" checkbox is selected or not. If it is selected, then loop through all items in testData and set their "sel" properties to true. Otherwise, loop through them and set the values to false.
Whats worth noticing is that all List-like components in Flex (such as List, DataGrid and TileList) dont always create a separate item renderer for each item in the data provider. For example, if we have 500 items in the List, it doesnt mean that the List will have 500 item renderers that all display values for their own assigned items. In these situations, the component usually has a scrollbar (or even two) and not all of the items are visible. For example, only 10 items might be visible out of 500 at a time. The List component just displays 10 and changes their values as the user scrolls through the content.
This boosts up the performance a lot, but can also cause some problems. Like in our situation - if we have a lot of items in the datagrid, say, 100, we obviously wont be able to view all of them at the same time, maybe around 15 at a time - the data grid will only display these 15 visible items.
Whats the problem then? Its that if we use custom modifications, such as CheckBoxes as item renderers of the columns, they also keep their properties like "selected" even if the item renderer is switched to display another item, which might have a different value.
To prevent this, we must bind the select value to data.sel using the {} braces. Because our check boxes are also editable (the user can tick and untick them), we two-way-bind them using @{data.sel}.
Full code so far:
Thanks for reading!
Read more »
Firstly, well turn the contents of the first NavigatorContent object into a VGroup, which contains an HBox (something I added just now) and an AdvancedDataGrid that we already have.
The HBox is a container which will contain some tools for editing the data grid. Well add a new column to the datagrid today, which will be a column of CheckBox objects. This way the user will be able to select one or multiple items to perform an action on all of them, for example, delete them all.
For this feature specifically the HBox will contain a CheckBox which will allow the user to select or deselect all of the entries in the table. Set its label to "Select all" and set its change event listener to a function called selectAllChange(), and pass "event" in the parameter. Next to the checkbox, add a button (which does nothing right now) with a label "Delete selected".
<mx:HBox width="100%" height="30" paddingLeft="8" paddingTop="6">
<mx:CheckBox label="Select all" change="selectAllChange(event);" />
<s:Button label="Delete selected" />
</mx:HBox>
In the AdvancedDataGrid itself, well do quite a few changes too. First, set its id to tableGrid. Set its editable property to true.
In the columns array, add a new AdvancedDataGridColumn object with blank headerText and width of 30. Set its sortable, draggable, editable and resizable properties to false. Set this particular columns itemRenderer to an fx:Component container, which contains an mx:Box container, which contains a CheckBox object. Set this CheckBoxs selected property bound to data.sel.
Set the idnum columns editable property to false. Those are all the changes we made to the data grid:
<mx:AdvancedDataGrid id="tableGrid" width="100%" height="100%" dataProvider="{testData}" editable="true">
<mx:columns>
<mx:AdvancedDataGridColumn headerText=" " width="30" sortable="false" draggable="false" resizable="false" editable="false">
<mx:itemRenderer>
<fx:Component>
<mx:Box width="30" horizontalAlign="center">
<mx:CheckBox selected="@{data.sel}" />
</mx:Box>
</fx:Component>
</mx:itemRenderer>
</mx:AdvancedDataGridColumn>
<mx:AdvancedDataGridColumn dataField="idnum" headerText="ID" editable="false" />
<mx:AdvancedDataGridColumn dataField="firstname" headerText="First name" />
<mx:AdvancedDataGridColumn dataField="lastname" headerText="Last name" />
<mx:AdvancedDataGridColumn dataField="age" headerText="Age"/>
</mx:columns>
</mx:AdvancedDataGrid>
The "sel" property of the "data" object is a boolean variable that is set in the testData array collection. Lets add that to all the items in the array and set the values to false. Lets also increase the number of objects in the array for testing purposes:
<mx:ArrayCollection id="testData">
<fx:Object idnum="1" sel="false" firstname="John" lastname="Jackson" age="32" />
<fx:Object idnum="2" sel="false" firstname="Ted" lastname="Jacobson" age="25" />
<fx:Object idnum="3" sel="false" firstname="Bob" lastname="Smith" age="33" />
<fx:Object idnum="4" sel="false" firstname="John" lastname="Jackson" age="32" />
<fx:Object idnum="5" sel="false" firstname="Ted" lastname="Jacobson" age="25" />
<fx:Object idnum="6" sel="false" firstname="Bob" lastname="Smith" age="33" />
<fx:Object idnum="7" sel="false" firstname="John" lastname="Jackson" age="32" />
<fx:Object idnum="8" sel="false" firstname="Ted" lastname="Jacobson" age="25" />
<fx:Object idnum="9" sel="false" firstname="Bob" lastname="Smith" age="33" />
<fx:Object idnum="10" sel="false" firstname="John" lastname="Jackson" age="32" />
<fx:Object idnum="11" sel="false" firstname="Ted" lastname="Jacobson" age="25" />
<fx:Object idnum="12" sel="false" firstname="Bob" lastname="Smith" age="33" />
<fx:Object idnum="13" sel="false" firstname="John" lastname="Jackson" age="32" />
<fx:Object idnum="14" sel="false" firstname="Ted" lastname="Jacobson" age="25" />
<fx:Object idnum="15" sel="false" firstname="Bob" lastname="Smith" age="33" />
<fx:Object idnum="16" sel="false" firstname="John" lastname="Jackson" age="32" />
<fx:Object idnum="17" sel="false" firstname="Ted" lastname="Jacobson" age="25" />
<fx:Object idnum="18" sel="false" firstname="Bob" lastname="Smith" age="33" />
</mx:ArrayCollection>
Now create fx:Script tags to create a function called selectAllChange(). This function checks if the "Select all" checkbox is selected or not. If it is selected, then loop through all items in testData and set their "sel" properties to true. Otherwise, loop through them and set the values to false.
<fx:Script>
<![CDATA[
import flash.events.Event;
import mx.controls.Alert;
private function selectAllChange(evt:Event):void {
var i:int;
if (evt.currentTarget.selected) {
for (i = 0; i < testData.length; i++) {
testData[i].sel = true;
}
} else
if (!evt.currentTarget.selected) {
for (i = 0; i < testData.length; i++) {
testData[i].sel = false;
}
}
tableGrid.invalidateDisplayList();
tableGrid.invalidateList();
}
]]>
</fx:Script>
Whats worth noticing is that all List-like components in Flex (such as List, DataGrid and TileList) dont always create a separate item renderer for each item in the data provider. For example, if we have 500 items in the List, it doesnt mean that the List will have 500 item renderers that all display values for their own assigned items. In these situations, the component usually has a scrollbar (or even two) and not all of the items are visible. For example, only 10 items might be visible out of 500 at a time. The List component just displays 10 and changes their values as the user scrolls through the content.
This boosts up the performance a lot, but can also cause some problems. Like in our situation - if we have a lot of items in the datagrid, say, 100, we obviously wont be able to view all of them at the same time, maybe around 15 at a time - the data grid will only display these 15 visible items.
Whats the problem then? Its that if we use custom modifications, such as CheckBoxes as item renderers of the columns, they also keep their properties like "selected" even if the item renderer is switched to display another item, which might have a different value.
To prevent this, we must bind the select value to data.sel using the {} braces. Because our check boxes are also editable (the user can tick and untick them), we two-way-bind them using @{data.sel}.
Full code so far:
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" showStatusBar="false">
<s:menu>
<mx:FlexNativeMenu dataProvider="{windowMenu}" showRoot="false" labelField="@label" keyEquivalentField="@key"/>
</s:menu>
<fx:Declarations>
<fx:XML id="windowMenu">
<root>
<menuitem label="Database">
<menuitem label="New" key="n" controlKey="true" />
<menuitem label="Open" key="o" controlKey="true" />
<menuitem label="Save" key="s" controlKey="true" />
<menuitem label="Save As.." key="s" controlKey="true" shiftKey="true" />
</menuitem>
<menuitem label="Table">
<menuitem label="New" key="t" controlKey="true" />
<menuitem label="Edit" key="e" controlKey="true" />
<menuitem label="Delete"/>
</menuitem>
</root>
</fx:XML>
<fx:XMLList id="testTree">
<root>
<treeitem label="Database1">
<treeitem label="Table1"/>
<treeitem label="Table2"/>
<treeitem label="Table3"/>
</treeitem>
</root>
</fx:XMLList>
<mx:ArrayCollection id="testData">
<fx:Object idnum="1" sel="false" firstname="John" lastname="Jackson" age="32" />
<fx:Object idnum="2" sel="false" firstname="Ted" lastname="Jacobson" age="25" />
<fx:Object idnum="3" sel="false" firstname="Bob" lastname="Smith" age="33" />
<fx:Object idnum="4" sel="false" firstname="John" lastname="Jackson" age="32" />
<fx:Object idnum="5" sel="false" firstname="Ted" lastname="Jacobson" age="25" />
<fx:Object idnum="6" sel="false" firstname="Bob" lastname="Smith" age="33" />
<fx:Object idnum="7" sel="false" firstname="John" lastname="Jackson" age="32" />
<fx:Object idnum="8" sel="false" firstname="Ted" lastname="Jacobson" age="25" />
<fx:Object idnum="9" sel="false" firstname="Bob" lastname="Smith" age="33" />
<fx:Object idnum="10" sel="false" firstname="John" lastname="Jackson" age="32" />
<fx:Object idnum="11" sel="false" firstname="Ted" lastname="Jacobson" age="25" />
<fx:Object idnum="12" sel="false" firstname="Bob" lastname="Smith" age="33" />
<fx:Object idnum="13" sel="false" firstname="John" lastname="Jackson" age="32" />
<fx:Object idnum="14" sel="false" firstname="Ted" lastname="Jacobson" age="25" />
<fx:Object idnum="15" sel="false" firstname="Bob" lastname="Smith" age="33" />
<fx:Object idnum="16" sel="false" firstname="John" lastname="Jackson" age="32" />
<fx:Object idnum="17" sel="false" firstname="Ted" lastname="Jacobson" age="25" />
<fx:Object idnum="18" sel="false" firstname="Bob" lastname="Smith" age="33" />
</mx:ArrayCollection>
</fx:Declarations>
<fx:Script>
<![CDATA[
import flash.events.Event;
import mx.controls.Alert;
private function selectAllChange(evt:Event):void {
var i:int;
if (evt.currentTarget.selected) {
for (i = 0; i < testData.length; i++) {
testData[i].sel = true;
}
} else
if (!evt.currentTarget.selected) {
for (i = 0; i < testData.length; i++) {
testData[i].sel = false;
}
}
tableGrid.invalidateDisplayList();
tableGrid.invalidateList();
}
]]>
</fx:Script>
<s:HGroup gap="0" width="100%" height="100%">
<s:VGroup width="200" height="100%" gap="0">
<mx:Tree width="100%" height="100%" dataProvider="{testTree}" showRoot="false" labelField="@label"/>
</s:VGroup>
<s:VGroup width="100%" height="100%" gap="0">
<mx:TabNavigator width="100%" height="100%" paddingTop="0">
<s:NavigatorContent label="Table contents">
<s:VGroup width="100%" height="100%" gap="0">
<mx:HBox width="100%" height="30" paddingLeft="8" paddingTop="6">
<mx:CheckBox label="Select all" change="selectAllChange(event);" />
<s:Button label="Delete selected" />
</mx:HBox>
<mx:AdvancedDataGrid id="tableGrid" width="100%" height="100%" dataProvider="{testData}" editable="true">
<mx:columns>
<mx:AdvancedDataGridColumn headerText=" " width="30" sortable="false" draggable="false" resizable="false" editable="false">
<mx:itemRenderer>
<fx:Component>
<mx:Box width="30" horizontalAlign="center">
<mx:CheckBox selected="@{data.sel}" />
</mx:Box>
</fx:Component>
</mx:itemRenderer>
</mx:AdvancedDataGridColumn>
<mx:AdvancedDataGridColumn dataField="idnum" headerText="ID" editable="false" />
<mx:AdvancedDataGridColumn dataField="firstname" headerText="First name" />
<mx:AdvancedDataGridColumn dataField="lastname" headerText="Last name" />
<mx:AdvancedDataGridColumn dataField="age" headerText="Age"/>
</mx:columns>
</mx:AdvancedDataGrid>
</s:VGroup>
</s:NavigatorContent>
<s:NavigatorContent label="Edit columns">
</s:NavigatorContent>
<s:NavigatorContent label="Query">
</s:NavigatorContent>
</mx:TabNavigator>
</s:VGroup>
</s:HGroup>
</s:WindowedApplication>
Thanks for reading!
Creating a Flex AIR Screenshot app Part 18
In this part we will add labels that display width and height of the selected area to the user, as well as add a cursor for cropping.
Go to the "crop" NavigatorContent object and add 2 labels there. Set their ids to displayWidth and displayHeight, colors to black and mouseEnabled properties to false.
Now, lets go to the drawRectangle() function and set coordinates and text values for these two labels. We can use values from the drawingRect array:
There might be problems with readability of the labels if we leave them like that, so lets add some thick glow filters that create a white stroke around the characters and make them readable on any background.
Go to changeState(), in the crop conditional add 2 lines that set filters for these two objects like this:
Now, we will add a cursor that appears when the user rolls over the crop area and returns to normal cursor when he roll out. Ive drawn my cursor myself, it is a 19x19 png image and looks like this:
Draw your own or use the one I made and save it as cursor_crop.png in the lib folder of the project.
Go to changeState() again, in the crop conditional add MOUSE_OVER and MOUSE_OUT event listeners for the drawArea object:
Go to the beginning of the script and declare a new variable cropCursor, typed Class. On a line above it embed the cursor_crop.png cursor image we have. This will attach the image to the variable below.
The drawOver() and drawOut() functions should display and hide the custom cursor. We can do that using cursorManager class, and its setCursor() and removeAllCursors() methods. In the first one, well have to specify a few parameters for it to display correctly:
And thats it for today!
Full code:
Thanks for reading!
Read more »
Go to the "crop" NavigatorContent object and add 2 labels there. Set their ids to displayWidth and displayHeight, colors to black and mouseEnabled properties to false.
<s:NavigatorContent id="crop">
<s:VGroup width="{contentBox.width}" height="100%" gap="0" horizontalAlign="center">
<mx:HBox backgroundColor="#999999" width="100%" height="24" verticalScrollPolicy="off" verticalAlign="middle" paddingLeft="2">
<s:Button label="Back" click="{stack.selectedChild = loadpage;}" />
<s:Button label="Export selection" enabled="false" />
</mx:HBox>
<s:Scroller width="{(contentBox.width>cropHTML.width+15)?(cropHTML.width+15):(contentBox.width)}" height="{contentBox.height-24}">
<s:Group>
<s:BitmapImage id="cropHTML" />
<s:SpriteVisualElement id="cropDraw" width="{cropHTML.width}" height="{cropHTML.height}" />
<mx:Box width="{cropHTML.width}" height="{cropHTML.height}" alpha="0" id="drawArea" backgroundColor="#000000"/>
<s:Label id="displayWidth" color="#000000" mouseEnabled="false" />
<s:Label id="displayHeight" color="#000000" mouseEnabled="false" />
</s:Group>
</s:Scroller>
</s:VGroup>
</s:NavigatorContent>
Now, lets go to the drawRectangle() function and set coordinates and text values for these two labels. We can use values from the drawingRect array:
private function drawRectangle():void {
displayWidth.x = drawingRect[0];
displayWidth.y = drawingRect[1] - 12;
displayWidth.text = Math.abs(drawingRect[2]) + "px";
displayHeight.x = drawingRect[0] + drawingRect[2] + 4;
displayHeight.y = drawingRect[1] + drawingRect[3] - 12;
displayHeight.text = Math.abs(drawingRect[3]) + "px";
cropDraw.graphics.clear();
cropDraw.graphics.lineStyle(1, 0xff0000);
cropDraw.graphics.beginFill(0x00ff00, 0.15);
cropDraw.graphics.drawRect(drawingRect[0], drawingRect[1], drawingRect[2], drawingRect[3]);
cropDraw.graphics.endFill();
}
There might be problems with readability of the labels if we leave them like that, so lets add some thick glow filters that create a white stroke around the characters and make them readable on any background.
Go to changeState(), in the crop conditional add 2 lines that set filters for these two objects like this:
displayWidth.filters = [new GlowFilter(0xffffff, 1, 3, 3, 50)];
displayHeight.filters = [new GlowFilter(0xffffff, 1, 3, 3, 50)];
Now, we will add a cursor that appears when the user rolls over the crop area and returns to normal cursor when he roll out. Ive drawn my cursor myself, it is a 19x19 png image and looks like this:
Draw your own or use the one I made and save it as cursor_crop.png in the lib folder of the project.
Go to changeState() again, in the crop conditional add MOUSE_OVER and MOUSE_OUT event listeners for the drawArea object:
drawArea.addEventListener(MouseEvent.MOUSE_OVER, drawOver);
drawArea.addEventListener(MouseEvent.MOUSE_OUT, drawOut);
Go to the beginning of the script and declare a new variable cropCursor, typed Class. On a line above it embed the cursor_crop.png cursor image we have. This will attach the image to the variable below.
[Embed(source="../lib/cursor_crop.png")]
private var cropCursor:Class;
The drawOver() and drawOut() functions should display and hide the custom cursor. We can do that using cursorManager class, and its setCursor() and removeAllCursors() methods. In the first one, well have to specify a few parameters for it to display correctly:
private function drawOver(evt:MouseEvent):void {
cursorManager.setCursor(cropCursor, 2, -9, -9);
}
private function drawOut(evt:MouseEvent):void {
cursorManager.removeAllCursors();
}
And thats it for today!
Full code:
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:custom="*"
xmlns:mx="library://ns.adobe.com/flex/mx" showStatusBar="false"
width="550" height="600" creationComplete="init();">
<fx:Declarations>
<mx:ArrayCollection id="headerTitles">
<fx:Object step="Step one:" description="load a web page." />
<fx:Object step="Loading..." description="please wait." />
<fx:Object step="Step two:" description="set your export preferences." />
<fx:Object step="Step two:" description="select the area you wish to crop." />
<fx:Object step="Step three:" description="set your export preferences for the cropped image." />
<fx:Object step="Exporting:" description="please wait." />
</mx:ArrayCollection>
</fx:Declarations>
<fx:Style>
@namespace s "library://ns.adobe.com/flex/spark";
@namespace mx "library://ns.adobe.com/flex/mx";
.descriptionText{
fontSize: 24;
color: #fff;
}
.descriptionText2{
fontSize: 16;
color: #fff;
}
.settingText{
fontSize: 16;
color: #fff;
}
#headStep{
fontSize: 30;
fontWeight: bold;
color: #ffffbb;
}
#headDesc{
fontSize: 30;
color: #ffffff;
}
</fx:Style>
<fx:Script>
<![CDATA[
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.filesystem.File;
import flash.filesystem.FileStream;
import flash.filters.GlowFilter;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.net.URLRequest;
import flash.utils.ByteArray;
import flash.utils.Timer;
import mx.controls.HTML;
import mx.core.FlexHTMLLoader;
import mx.events.FlexNativeWindowBoundsEvent;
import mx.controls.Alert;
import mx.events.ResizeEvent;
import mx.graphics.codec.IImageEncoder;
import mx.graphics.codec.JPEGEncoder;
import mx.graphics.codec.PNGEncoder;
import mx.graphics.ImageSnapshot;
import spark.primitives.BitmapImage;
import flash.filesystem.FileMode;
import mx.managers.PopUpManager;
[Bindable]
private var urlString:String;
private var tempHTML:HTML = new HTML();
private var preferences:SharedObject = SharedObject.getLocal("kirshotPreferences");
[Bindable]
private var pref_screensizes:Array;
[Bindable]
private var pref_format:String;
[Bindable]
private var pref_quality:int;
[Bindable]
private var pref_folder:Boolean;
[Bindable]
private var pref_destination:String;
[Bindable]
private var exportText:String;
private var screenGo:String;
private var drawing:Boolean = false;
private var drawingRect:Array = [];
[Embed(source="../lib/cursor_crop.png")]
private var cropCursor:Class;
private var screenSettings:Array;
private function init():void {
//preferences.data.firsttime = null;
// Set preferences if loaded for the first time
if (preferences.data.firsttime == null) {
preferences.data.firsttime = true;
preferences.data.screensizes = [
{ checked:true },
{ checked:true, w:1280, h:1024 },
{ checked:true, w:1280, h:800 },
{ checked:true, w:1024, h:768 },
{ checked:false, w:"", h:"" },
{ checked:false, w:"", h:"" },
{ checked:false, w:"", h:"" } ];
preferences.data.format = "JPEG";
preferences.data.quality = 100;
preferences.data.folder = true;
preferences.data.destination = File.documentsDirectory.nativePath;
preferences.flush();
}
// Set preferences loaded from local storage
pref_screensizes = preferences.data.screensizes;
pref_format = preferences.data.format;
pref_quality = preferences.data.quality;
pref_folder = preferences.data.folder;
pref_destination = preferences.data.destination;
addElement(tempHTML);
removeElement(tempHTML);
}
private function doBrowse():void{
var file:File = new File();
file.addEventListener(Event.SELECT, browseSelect);
file.browseForOpen("Load a webpage");
function browseSelect(evt:Event):void {
urlInput.text = file.nativePath;
}
}
private function goScreenshot(screen:String):void {
screenGo = screen;
stack.selectedChild = screenshotloading;
urlString = urlInput.text;
addElement(tempHTML);
tempHTML.htmlLoader.useCache = false;
tempHTML.horizontalScrollPolicy = "off";
tempHTML.verticalScrollPolicy = "off";
tempHTML.visible = false;
tempHTML.addEventListener(Event.COMPLETE, onTempLoad);
tempHTML.htmlLoader.load(new URLRequest(urlString));
}
private function onTempLoad(evt:Event):void {
tempHTML.removeEventListener(Event.COMPLETE, onTempLoad);
if(screenGo=="screenshot"){
stack.selectedChild = screenshotsettings;
}
if (screenGo == "crop") {
if(tempHTML.contentWidth <= 4096 && tempHTML.contentHeight <= 4096){
var t:Timer = new Timer(1000, 1);
t.addEventListener(TimerEvent.TIMER_COMPLETE, tComplete);
t.start();
tempHTML.width = tempHTML.contentWidth;
tempHTML.height = tempHTML.contentHeight;
function tComplete(evt:TimerEvent):void {
stack.selectedChild = crop;
}
}else {
Alert.show("Dimensions of a screenshot cannot exceed 4096 pixels.", "Sorry...");
stack.selectedChild = loadpage;
}
}
}
private function cancelLoading():void {
tempHTML.removeEventListener(Event.COMPLETE, onTempLoad);
tempHTML.cancelLoad();
stack.selectedChild = loadpage;
removeElement(tempHTML);
}
private function screenshotBack():void {
saveScreenshotSettings();
stack.selectedChild = loadpage;
removeElement(tempHTML);
}
private function changeState():void {
if (stack.selectedChild == loadpage) {
contentBox.setStyle("horizontalAlign", "center");
urlInput.text = urlString;
tempHTML.width = 1;
tempHTML.height = 1;
tempHTML.removeEventListener(Event.COMPLETE, onTempLoad);
tempHTML.htmlLoader.loadString("<html></html>");
}
if (stack.selectedChild == crop) {
maximize();
contentBox.setStyle("horizontalAlign", "left");
var bd:BitmapData = new BitmapData(tempHTML.width, tempHTML.height, false);
bd.draw(tempHTML);
var b:Bitmap = new Bitmap(bd, "auto", true);
cropHTML.source = b;
drawArea.addEventListener(MouseEvent.MOUSE_DOWN, drawDown);
addEventListener(MouseEvent.MOUSE_UP, drawUp);
drawArea.addEventListener(MouseEvent.MOUSE_MOVE, drawMove);
displayWidth.filters = [new GlowFilter(0xffffff, 1, 3, 3, 50)];
displayHeight.filters = [new GlowFilter(0xffffff, 1, 3, 3, 50)];
drawArea.addEventListener(MouseEvent.MOUSE_OVER, drawOver);
drawArea.addEventListener(MouseEvent.MOUSE_OUT, drawOut);
}
if (stack.selectedChild == screenshotsettings) {
screenSettings = [set2, set3, set4, set5, set6, set7];
contSize.text = "Full size (" + tempHTML.contentWidth + "x" + tempHTML.contentHeight + ")";
loadScreenshotSettings();
}
}
private function loadScreenshotSettings():void {
set1checkbox.selected = pref_screensizes[0].checked;
for (var i:int = 0; i < screenSettings.length; i++) {
screenSettings[i].checked = pref_screensizes[i + 1].checked;
screenSettings[i].w = pref_screensizes[i + 1].w;
screenSettings[i].h = pref_screensizes[i + 1].h;
}
if (pref_format == "JPEG") {
screenRadioJPEG.selected = true;
} else {
screenRadioPNG.selected = true;
}
}
private function saveScreenshotSettings():void {
pref_screensizes[0].checked = set1checkbox.selected;
for (var i:int = 0; i < screenSettings.length; i++) {
pref_screensizes[i + 1].checked = screenSettings[i].checked;
pref_screensizes[i + 1].w = screenSettings[i].w;
pref_screensizes[i + 1].h = screenSettings[i].h;
}
if (screenRadioJPEG.selected == true) {
pref_format == "JPEG";
} else {
pref_format == "PNG";
}
preferences.data.screensizes = pref_screensizes;
preferences.data.format = pref_format;
preferences.data.quality = pref_quality;
preferences.data.folder = pref_folder;
preferences.data.destination = pref_destination;
preferences.flush();
}
private function formatChange(newformat:String):void {
pref_format = newformat;
}
private function startExportScreenshot():void {
var canExport:Boolean = true;
for (var i:int = 0; i < screenSettings.length; i++) {
if (screenSettings[i].checked && ((screenSettings[i].w == "" || screenSettings[i].w == 0) || (screenSettings[i].h == "" || screenSettings[i].h == 0))) {
canExport = false;
}
}
if (canExport) {
if ((pref_folder && folderField.text != "") || !pref_folder) {
saveScreenshotSettings();
exportScreen();
}else {
Alert.show("Folder name should not be blank!", "Oops...");
}
}else {
Alert.show("One or more selected screen sizes are not entered or are invalid!", "Oops...");
}
}
private function screenshotDestination():void {
var newDestination:File = new File(pref_destination);
newDestination.browseForDirectory("Select directory");
newDestination.addEventListener(Event.SELECT, destinationSelect);
function destinationSelect(evt:Event):void {
pref_destination = newDestination.nativePath;
}
}
private function exportScreen():void {
var encoder:IImageEncoder;
var bd:BitmapData;
var byteArray:ByteArray;
var folderName:String = (pref_folder)?(folderField.text):("");
var fileName:String;
var file:File;
var fileStream:FileStream;
var screensToExport:Array = [];
stack.selectedChild = export;
if (pref_format == "JPEG") {
encoder = new JPEGEncoder(pref_quality);
}
if (pref_format == "PNG") {
encoder = new PNGEncoder();
}
// add full-size screen to array if checked
if (pref_screensizes[0].checked) {
screensToExport = [ { w:tempHTML.contentWidth, h: tempHTML.contentHeight, full:true} ];
}
// add the rest screens to array if checked
for (var i:int = 0; i < screenSettings.length; i++) {
if (pref_screensizes[i + 1].checked) {
screensToExport.push( { w: pref_screensizes[i + 1].w, h:pref_screensizes[i + 1].h } );
}
}
// if nothing is checked, go to first page and stop code
if (screensToExport.length == 0) {
removeElement(tempHTML);
stack.selectedChild = loadpage;
return;
}
// create a timer that repeats itself as many times as many items there are in the array
var timer:Timer = new Timer(2000, screensToExport.length);
timer.addEventListener(TimerEvent.TIMER, onTimer);
// set sizes to the first size of the array
if (screensToExport[0].full) {
tempHTML.horizontalScrollPolicy = "off";
tempHTML.verticalScrollPolicy = "off";
}else {
tempHTML.horizontalScrollPolicy = "auto";
tempHTML.verticalScrollPolicy = "auto";
}
if(screensToExport[0].h <= 4096 && screensToExport[0].w <= 4096){
tempHTML.height = screensToExport[0].h;
tempHTML.width = screensToExport[0].w;
}
updateExportText(screensToExport[0].w, screensToExport[0].h, 1, screensToExport.length);
timer.start();
function onTimer(evt:TimerEvent):void {
// do export for the current size
if(screensToExport[timer.currentCount-1].h <= 4096 && screensToExport[timer.currentCount-1].w <= 4096){
timer.stop();
doExport();
timer.start();
}else {
Alert.show("Cannot export " + screensToExport[timer.currentCount-1].w + "x" + screensToExport[timer.currentCount-1].h + " - dimensions of a screenshot cannot extend 4096.","Sorry");
}
// change the size if this was not the last size in the array
if (timer.currentCount != screensToExport.length) {
tempHTML.horizontalScrollPolicy = "auto";
tempHTML.verticalScrollPolicy = "auto";
if(screensToExport[timer.currentCount].h <= 4096 && screensToExport[timer.currentCount].w <= 4096){
tempHTML.height = screensToExport[timer.currentCount].h;
tempHTML.width = screensToExport[timer.currentCount].w;
}
updateExportText(screensToExport[timer.currentCount].w, screensToExport[timer.currentCount].h, timer.currentCount+1, screensToExport.length);
}else {
// if it was the last size in the array, return to first page
timer.stop();
removeElement(tempHTML);
stack.selectedChild = loadpage;
}
}
function doExport():void {
bd = new BitmapData(tempHTML.width, tempHTML.height, false);
bd.draw(tempHTML, null, null, null, null, true);
byteArray = encoder.encode(bd);
fileName = pref_destination + File.separator + folderName + File.separator + tempHTML.width + "x" + tempHTML.height + "." + pref_format;
file = new File(fileName);
fileStream = new FileStream();
fileStream.open(file, FileMode.WRITE);
fileStream.writeBytes(byteArray);
fileStream.close();
}
function updateExportText(w:int, h:int, current:int, total:int):void {
exportText = "Exporting " + w + "x" + h + "." + pref_format + " (" + current + "/" + total + ")";
}
}
private function drawDown(evt:MouseEvent):void {
drawing = true;
drawingRect = [evt.target.mouseX, evt.target.mouseY, 0, 0];
drawRectangle();
}
private function drawUp(evt:MouseEvent):void{
drawing = false;
}
private function drawMove(evt:MouseEvent):void{
if (drawing) {
drawingRect[2] = evt.target.mouseX - drawingRect[0];
drawingRect[3] = evt.target.mouseY - drawingRect[1];
drawRectangle();
}
}
private function drawRectangle():void {
displayWidth.x = drawingRect[0];
displayWidth.y = drawingRect[1] - 12;
displayWidth.text = Math.abs(drawingRect[2]) + "px";
displayHeight.x = drawingRect[0] + drawingRect[2] + 4;
displayHeight.y = drawingRect[1] + drawingRect[3] - 12;
displayHeight.text = Math.abs(drawingRect[3]) + "px";
cropDraw.graphics.clear();
cropDraw.graphics.lineStyle(1, 0xff0000);
cropDraw.graphics.beginFill(0x00ff00, 0.15);
cropDraw.graphics.drawRect(drawingRect[0], drawingRect[1], drawingRect[2], drawingRect[3]);
cropDraw.graphics.endFill();
}
private function drawOver(evt:MouseEvent):void {
cursorManager.setCursor(cropCursor, 2, -9, -9);
}
private function drawOut(evt:MouseEvent):void {
cursorManager.removeAllCursors();
}
]]>
</fx:Script>
<s:VGroup width="100%" height="100%" gap="0">
<mx:HBox backgroundColor="#333333" height="46" width="100%" paddingTop="10" paddingLeft="10">
<s:Label id="headStep" text="{headerTitles.getItemAt(stack.selectedIndex).step}" />
<s:Label id="headDesc" text="{headerTitles.getItemAt(stack.selectedIndex).description}" />
</mx:HBox>
<mx:Box backgroundColor="#666666" width="100%" height="100%" id="contentBox" horizontalAlign="center">
<mx:ViewStack id="stack" change="changeState();">
<s:NavigatorContent id="loadpage">
<s:VGroup width="100%" horizontalAlign="center" paddingTop="20">
<s:Label styleName="descriptionText">Enter the link to the page:</s:Label>
<s:HGroup>
<s:TextInput width="250" id="urlInput" text="http://" /><s:Button label="Browse local..." click="doBrowse();" />
</s:HGroup>
<s:HGroup>
<custom:ImageButton img="@Embed(../lib/b_screenshot.png)" over="@Embed(../lib/b_screenshot_over.png)" toolTip="Take screenshots" click="goScreenshot(screenshot);" buttonMode="true" enabled="{urlInput.text!=}" />
<custom:ImageButton img="@Embed(../lib/b_cut.png)" over="@Embed(../lib/b_cut_over.png)" toolTip="Crop area" click="goScreenshot(crop);" buttonMode="true" enabled="{urlInput.text!=}" />
</s:HGroup>
</s:VGroup>
</s:NavigatorContent>
<s:NavigatorContent id="screenshotloading">
<s:VGroup width="100%" horizontalAlign="center" paddingTop="20">
<s:Label styleName="descriptionText">The page is being loaded...</s:Label>
<s:Button label="Cancel" click="cancelLoading();" />
</s:VGroup>
</s:NavigatorContent>
<s:NavigatorContent id="screenshotsettings">
<s:VGroup width="100%" horizontalAlign="center" paddingTop="20">
<s:Label styleName="descriptionText2">Select screenshot screen sizes:</s:Label>
<s:SkinnableContainer backgroundColor="#999999" width="310" height="18" >
<s:CheckBox toolTip="Use this screen size" x="4" id="set1checkbox" />
<s:Label id="contSize" styleName="settingText" x="22" y="3" />
</s:SkinnableContainer>
<custom:ScreenSetting id="set2" />
<custom:ScreenSetting id="set3" />
<custom:ScreenSetting id="set4" />
<custom:ScreenSetting id="set5" />
<custom:ScreenSetting id="set6" />
<custom:ScreenSetting id="set7" />
<s:Label/>
<s:Label styleName="descriptionText2">Export as:</s:Label>
<s:HGroup>
<s:RadioButton id="screenRadioJPEG" label="JPEG" groupName="screenshotFormat" change="formatChange(JPEG);" styleName="descriptionText2" />
<s:RadioButton id="screenRadioPNG" label="PNG" groupName="screenshotFormat" change="formatChange(PNG);" styleName="descriptionText2" />
</s:HGroup>
<s:Label styleName="descriptionText2">Quality:</s:Label>
<s:HSlider id="screenQualitySlider" width="310" minimum="1" maximum="100" liveDragging="true" enabled="{pref_format==JPEG}" value="@{pref_quality}" />
<s:Label/>
<s:Label styleName="descriptionText2">Export destination:</s:Label>
<s:HGroup width="310">
<s:TextInput editable="false" width="100%" toolTip="Destination" text="{pref_destination}" />
<s:Button label="Browse" click="screenshotDestination();" />
</s:HGroup>
<s:CheckBox id="folderCheckbox" label="Create new folder with exported images" styleName="descriptionText2" selected="@{pref_folder}" />
<s:TextInput id="folderField" width="100%" toolTip="Folder name" maxChars="200" enabled="{folderCheckbox.selected}" restrict="a-zA-Z0-9._-=+" />
<s:HGroup>
<s:Button label="Back" click="screenshotBack();" />
<s:Button label="Export" click="startExportScreenshot();" />
</s:HGroup>
</s:VGroup>
</s:NavigatorContent>
<s:NavigatorContent id="crop">
<s:VGroup width="{contentBox.width}" height="100%" gap="0" horizontalAlign="center">
<mx:HBox backgroundColor="#999999" width="100%" height="24" verticalScrollPolicy="off" verticalAlign="middle" paddingLeft="2">
<s:Button label="Back" click="{stack.selectedChild = loadpage;}" />
<s:Button label="Export selection" enabled="false" />
</mx:HBox>
<s:Scroller width="{(contentBox.width>cropHTML.width+15)?(cropHTML.width+15):(contentBox.width)}" height="{contentBox.height-24}">
<s:Group>
<s:BitmapImage id="cropHTML" />
<s:SpriteVisualElement id="cropDraw" width="{cropHTML.width}" height="{cropHTML.height}" />
<mx:Box width="{cropHTML.width}" height="{cropHTML.height}" alpha="0" id="drawArea" backgroundColor="#000000"/>
<s:Label id="displayWidth" color="#000000" mouseEnabled="false" />
<s:Label id="displayHeight" color="#000000" mouseEnabled="false" />
</s:Group>
</s:Scroller>
</s:VGroup>
</s:NavigatorContent>
<s:NavigatorContent id="cropsettings">
</s:NavigatorContent>
<s:NavigatorContent id="export">
<s:VGroup width="100%" horizontalAlign="center" paddingTop="20">
<s:Label styleName="descriptionText" text="{exportText}" />
</s:VGroup>
</s:NavigatorContent>
</mx:ViewStack>
</mx:Box>
</s:VGroup>
</s:WindowedApplication>
Thanks for reading!
Android beginner tutorial Part 81 RingtonePreference
In this part we will learn how to create and handle a RingtonePreference object.
A RingtonePreference is a settings item that lets the user pick a ringtone from their system. The selected ringtones URI address is saved in the preferences file, which can then be used by the application.
Firstly go to preferences.xml file and add a new RingtonePreference object. The attributes were going to set are android:key, android:title, android:summary, android:showDefault and android:showSilent. The first 3 were already used and explained in the previous tutorials, the last 2 are boolean values that determine whether the ringtone list should display the options to select default ringtone or set ringtone to silent.
So far the preferences.xml file looks like this:
Heres the updated strings.xml file with the new string values:
In the onResume() function of MainActivity.java, add a line that displays the URI of the ringtone:
Full class code looks like this:
And thats it. If you test your application now, youll see that theres a new preference item in the settings of your application.
The ringtone list lets you preview and select from default ringtones as well as the music library.
Thats all for today!
Thanks for reading!
Read more »
A RingtonePreference is a settings item that lets the user pick a ringtone from their system. The selected ringtones URI address is saved in the preferences file, which can then be used by the application.
Firstly go to preferences.xml file and add a new RingtonePreference object. The attributes were going to set are android:key, android:title, android:summary, android:showDefault and android:showSilent. The first 3 were already used and explained in the previous tutorials, the last 2 are boolean values that determine whether the ringtone list should display the options to select default ringtone or set ringtone to silent.
<RingtonePreference
android:key="pref_tone"
android:title="@string/pref_tone"
android:summary="@string/pref_tone_summ"
android:showDefault="true"
android:showSilent="true"/>
So far the preferences.xml file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:key="pref_mute"
android:title="@string/pref_mute"
android:summary="@string/pref_mute_summ"
android:defaultValue="false" />
<EditTextPreference
android:key="pref_textsize"
android:title="@string/pref_textsize"
android:dialogTitle="@string/pref_textsize_descr"
android:summary="@string/pref_textsize_summ"
android:defaultValue="14" />
<ListPreference
android:key="pref_theme"
android:title="@string/pref_theme"
android:dialogTitle="@string/pref_theme_descr"
android:summary="@string/pref_theme_summ"
android:entries="@array/theme_colors"
android:entryValues="@array/theme_colors"
android:defaultValue="Blue" />
<RingtonePreference
android:key="pref_tone"
android:title="@string/pref_tone"
android:summary="@string/pref_tone_summ"
android:showDefault="true"
android:showSilent="true"/>
</PreferenceScreen>
Heres the updated strings.xml file with the new string values:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">CodeForFood Test Two</string>
<string name="pref_mute">Mute</string>
<string name="pref_mute_summ">Disable all the sound in the application</string>
<string name="pref_textsize">Text size</string>
<string name="pref_textsize_descr">Enter text size</string>
<string name="pref_textsize_summ">Set text size of the interface</string>
<string name="pref_theme">Theme</string>
<string name="pref_theme_descr">Pick a color</string>
<string name="pref_theme_summ">Set the applications color theme</string>
<string name="pref_tone">Ringtone</string>
<string name="pref_tone_summ">Set ringtone</string>
<string name="menu_settings">Settings</string>
<string name="clear_settings">Reset settings</string>
</resources>
In the onResume() function of MainActivity.java, add a line that displays the URI of the ringtone:
Toast.makeText(this, "Ringtone: " + prefs.getString("pref_tone", "none"), Toast.LENGTH_SHORT).show();
Full class code looks like this:
package com.example.codeforfoodtest_two;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends Activity{
static final int IDM_SETTINGS = 101;
public SharedPreferences prefs;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn_clear = (Button)findViewById(R.id.clearButton);
btn_clear.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Editor editor = prefs.edit();
editor.clear();
editor.commit();
onResume();
}
});
}
@Override
public void onResume(){
prefs = PreferenceManager.getDefaultSharedPreferences(this);
if(prefs.getBoolean("pref_mute", false)){
Toast.makeText(this, "Muted!", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this, "Not muted!", Toast.LENGTH_SHORT).show();
}
Toast.makeText(this, "Text size: " + prefs.getString("pref_textsize", "14"), Toast.LENGTH_SHORT).show();
Toast.makeText(this, "Theme color: " + prefs.getString("pref_theme", "Blue"), Toast.LENGTH_SHORT).show();
Toast.makeText(this, "Ringtone: " + prefs.getString("pref_tone", "none"), Toast.LENGTH_SHORT).show();
super.onResume();
}
@Override
public boolean onCreateOptionsMenu(Menu menu){
menu.add(Menu.NONE, IDM_SETTINGS, Menu.NONE, R.string.menu_settings);
return(super.onCreateOptionsMenu(menu));
}
@Override
public boolean onOptionsItemSelected(MenuItem item){
if(item.getItemId()==IDM_SETTINGS){
Intent intent = new Intent();
intent.setClass(this, TestPreferences.class);
startActivity(intent);
}
return true;
}
}
And thats it. If you test your application now, youll see that theres a new preference item in the settings of your application.
The ringtone list lets you preview and select from default ringtones as well as the music library.
Thats all for today!
Thanks for reading!
Drupal 7 Tutorials Video Training Course with Demos
Drupal is one of the most well-known and widely-used open source content management systems out there today, and it powers millions of sites and applications throughout the web. As of this posting, the latest version is Drupal 7, which was released on January 5, 2011. For those interested in learning its new features, lynda.com online tutorials has released a series of Drupal 7 tutorials. In Drupal 7 Essential Training, computer journalist Tom Geller presents a series of video tutorials that will show you how to get the most out of this powerful and robust content management system (CMS). By the end of the course, you will have learned the necessary skills that will enable you to build a website using Drupal. The course will go through the basics of how to download and install Drupal, add content and graphics to a site, change the layout and design elements, control visitor interactions, and expand the sites capabilities beyond what’s available in Drupal core. Youll also learn about established best practices to ensure that your site remains streamlined, secure, and up-to-date.
Watch these selected videos to get a good idea of the pace and flow of this course:
If you liked these videos, then go ahead and sign up for a lynda.com online tutorials membership. For $25, you get 1-month unlimited access to not just this training course, but all of Lynda.coms 900+ training courses. No long-term commitment required. You can cancel your membership at any time. And as a special promotion for visitors of this site, you can get a FREE 7-day trial pass to lynda.com. This free trial gives you access to all of their 900+ training titles so that you can see for yourself what a great learning resource this website is.
The course is 7 hours and 25 minutes in total length, and the tutorials are divided into 17 chapters. Here is a more detailed outline of the course:
Title: Drupal 7 Essential Training
Author: Tom Geller
Level: Beginner
Duration: 7hrs 25mins
Date of Release: 14 January 2011
Chapter 1: Defining Drupal
Managing content with Drupal 7
Comparing Drupal with other content management systems
Deciding whether to use Drupal
Looking at Drupal-built sites
Exploring the Drupal universe
Getting help with Drupal issues
Chapter 2: Understanding How Drupal Works
Checking Drupals requirements
Investigating Drupals inner workings
Learning Drupals basic workflow
Understanding key terms in Drupal
Touring Drupals interface
Chapter 3: Installing Drupal on Mac OS X or Windows
Installing the Acquia Drupal stack installer (DAMP)
Importing core Drupal into DAMP
Running Drupals installer on top of DAMP
Chapter 4: Installing Drupal on a Server
Uploading Drupal with SFTP
Uploading Drupal with SSH
Creating Drupals MySQL database
Running Drupals installer
Installing Drupal using Acquias Debian/Ubuntu package
Chapter 5: Controlling Drupal 7
Using the toolbar
Using the shortcut bar
Touring the administrative controls
Customizing the Dashboard
Differentiating administrator and visitor views
Chapter 6: Building a Drupal Site
Understanding nodes
Creating basic content
Changing site information, graphics, and interface
Giving visitors a way to contact you
Chapter 7: Controlling Content
Creating content summaries
Revising content
Categorizing content with tags
Going further with content categories
Publishing content via RSS
Using text formats to prevent content damage
Setting the comment policy
Managing comments
Chapter 8: Enabling Other Content Types
Adding blogs
Adding discussion groups
Adding polls
Subscribing to RSS feeds
Categorizing RSS feeds
Chapter 9: Extending Content
Creating new content types
Adding fields to content types
Exploring field types and options
Adjusting field display
Customizing field display by context
Modifying image styles
Chapter 10: Managing Users
Defining new user policies
Creating user accounts
Setting up user profiles
Defining user roles
Controlling access permissions
Canceling user accounts
Chapter 11: Changing a Sites Interface
Understanding Drupal 7 page layout
Taking advantage of block regions
Creating and modifying blocks
Selecting and installing downloaded themes
Building themes the traditional way
Chapter 12: Helping Users Find Their Way Around
Understanding Drupal 7 default menus
Creating multilevel menus
Creating easy-to-navigate books
Chapter 13: Expanding a Sites Capabilities with Modules
Installing and uninstalling modules
Configuring modules
Surveying popular modules
Enabling styled text with a WYSIWYG editor
Chapter 14: Displaying Information with Views
Understanding views
Creating views
Modifying views
Chapter 15: Administrating Drupal
Launching a Drupal site
Troubleshooting a Drupal 7 installation
Backing up and restoring a Drupal site
Updating Drupal
Deleting Drupal
Chapter 16: Going Further with Drupal
Monitoring performance
Improving administration skills
Reviewing security and permissions
Adopting best practices
Chapter 17: Developing for Drupal
Programming modules
Joining the Drupal community
So if youre ready to start with Drupal 7 Essential Training, sign-up for a lynda.com online tutorials membership today.
Read more »
Watch these selected videos to get a good idea of the pace and flow of this course:
Drupal 7 Essential Training - Welcome
Drupal 7 Essential Training - Getting a Drupal site up fast
Drupal 7 Essential Training - Deciding whether to use Drupal
Drupal 7 Essential Training - Investigating Drupals inner workings
Drupal 7 Essential Training - Understanding nodes
Drupal 7 Essential Training - Adding fields to content types
Drupal 7 Essential Training - Modifying image styles
Drupal 7 Essential Training - Selecting and installing downloaded themes
Drupal 7 Essential Training - Enabling styled text with a WYSIWYG editor
Drupal 7 Essential Training - Launching a Drupal site
If you liked these videos, then go ahead and sign up for a lynda.com online tutorials membership. For $25, you get 1-month unlimited access to not just this training course, but all of Lynda.coms 900+ training courses. No long-term commitment required. You can cancel your membership at any time. And as a special promotion for visitors of this site, you can get a FREE 7-day trial pass to lynda.com. This free trial gives you access to all of their 900+ training titles so that you can see for yourself what a great learning resource this website is.
[Get a FREE 7-day trial pass to lynda.com TODAY]
The course is 7 hours and 25 minutes in total length, and the tutorials are divided into 17 chapters. Here is a more detailed outline of the course:
Title: Drupal 7 Essential Training
Author: Tom Geller
Level: Beginner
Duration: 7hrs 25mins
Date of Release: 14 January 2011
Chapter 1: Defining Drupal
Managing content with Drupal 7
Comparing Drupal with other content management systems
Deciding whether to use Drupal
Looking at Drupal-built sites
Exploring the Drupal universe
Getting help with Drupal issues
Chapter 2: Understanding How Drupal Works
Checking Drupals requirements
Investigating Drupals inner workings
Learning Drupals basic workflow
Understanding key terms in Drupal
Touring Drupals interface
Chapter 3: Installing Drupal on Mac OS X or Windows
Installing the Acquia Drupal stack installer (DAMP)
Importing core Drupal into DAMP
Running Drupals installer on top of DAMP
Chapter 4: Installing Drupal on a Server
Uploading Drupal with SFTP
Uploading Drupal with SSH
Creating Drupals MySQL database
Running Drupals installer
Installing Drupal using Acquias Debian/Ubuntu package
Chapter 5: Controlling Drupal 7
Using the toolbar
Using the shortcut bar
Touring the administrative controls
Customizing the Dashboard
Differentiating administrator and visitor views
Chapter 6: Building a Drupal Site
Understanding nodes
Creating basic content
Changing site information, graphics, and interface
Giving visitors a way to contact you
Chapter 7: Controlling Content
Creating content summaries
Revising content
Categorizing content with tags
Going further with content categories
Publishing content via RSS
Using text formats to prevent content damage
Setting the comment policy
Managing comments
Chapter 8: Enabling Other Content Types
Adding blogs
Adding discussion groups
Adding polls
Subscribing to RSS feeds
Categorizing RSS feeds
Chapter 9: Extending Content
Creating new content types
Adding fields to content types
Exploring field types and options
Adjusting field display
Customizing field display by context
Modifying image styles
Chapter 10: Managing Users
Defining new user policies
Creating user accounts
Setting up user profiles
Defining user roles
Controlling access permissions
Canceling user accounts
Chapter 11: Changing a Sites Interface
Understanding Drupal 7 page layout
Taking advantage of block regions
Creating and modifying blocks
Selecting and installing downloaded themes
Building themes the traditional way
Chapter 12: Helping Users Find Their Way Around
Understanding Drupal 7 default menus
Creating multilevel menus
Creating easy-to-navigate books
Chapter 13: Expanding a Sites Capabilities with Modules
Installing and uninstalling modules
Configuring modules
Surveying popular modules
Enabling styled text with a WYSIWYG editor
Chapter 14: Displaying Information with Views
Understanding views
Creating views
Modifying views
Chapter 15: Administrating Drupal
Launching a Drupal site
Troubleshooting a Drupal 7 installation
Backing up and restoring a Drupal site
Updating Drupal
Deleting Drupal
Chapter 16: Going Further with Drupal
Monitoring performance
Improving administration skills
Reviewing security and permissions
Adopting best practices
Chapter 17: Developing for Drupal
Programming modules
Joining the Drupal community
[Get a FREE 7-day pass to lynda.com TODAY]
So if youre ready to start with Drupal 7 Essential Training, sign-up for a lynda.com online tutorials membership today.
Friday, January 30, 2015
MySQL FULL JOIN
Here is a quick example on FULL JOIN in MySQL database.
FULL JOIN concept in MySQL is to return rows when there is a match in one of the tables. Further FULL JOIN or FULL OUTER JOIN is UNION of LEFT JOIN and the RIGHT JOIN of the both tables.
Consider that you have following two tables.
Table 1 : Persons
Eg : queries to create and populate the Persons table.
Table 2 : Invoice
Eg : queries to create and populate Invoice table.
Now think that we want to join rows of both these tables on the condition of same P_Id. To perform that we need to get the UNION of RIGHT JOIN and the LEFT JOIN of both tables.
Here is the query to FULL JOIN operation.
Resulting table :
I think that you can understand what happened here.
1. First result of LEFT OUTER JOIN of both tables.
2. Then result of RIGHT OUTER JOIN of both tables.
3. UNION of these two tables means rows when there is a match in one of the tables or FULL JOIN of these two tables.
If you understand the concept try to use following query to FULL JOIN these tables. Same concept and same result.
Thank you for watching. Always your ideas are welcome.
Happy coding!
Read more »
FULL JOIN concept in MySQL is to return rows when there is a match in one of the tables. Further FULL JOIN or FULL OUTER JOIN is UNION of LEFT JOIN and the RIGHT JOIN of the both tables.
Consider that you have following two tables.
Table 1 : Persons
Eg : queries to create and populate the Persons table.
CREATE TABLE Persons
(P_Id int, Name varchar(1));
INSERT INTO Persons
(P_Id, Name)
VALUES
(1, A),
(2, B),
(3, C),
(4, D),
(5, E);
Table 2 : Invoice
Eg : queries to create and populate Invoice table.
CREATE TABLE Invoice
(Id int, P_Id int);
INSERT INTO Invoice
(Id, P_Id)
VALUES
(111, 3),
(112, 3),
(113, 1),
(114, 1),
(115, 15);
Now think that we want to join rows of both these tables on the condition of same P_Id. To perform that we need to get the UNION of RIGHT JOIN and the LEFT JOIN of both tables.
Here is the query to FULL JOIN operation.
SELECT Persons.Name, Persons.P_Id, Invoice.Id
FROM Persons
LEFT JOIN Invoice
ON Persons.P_Id=Invoice.P_Id
UNION
SELECT Persons.Name, Persons.P_Id, Invoice.Id
FROM Persons
RIGHT JOIN Invoice
ON Persons.P_Id=Invoice.P_Id
Resulting table :
I think that you can understand what happened here.
1. First result of LEFT OUTER JOIN of both tables.
2. Then result of RIGHT OUTER JOIN of both tables.
3. UNION of these two tables means rows when there is a match in one of the tables or FULL JOIN of these two tables.
If you understand the concept try to use following query to FULL JOIN these tables. Same concept and same result.
SELECT Persons.Name, Persons.P_Id, Invoice.Id
FROM Persons
LEFT JOIN Invoice
ON Persons.P_Id=Invoice.P_Id
UNION
SELECT Persons.Name, Persons.P_Id, Invoice.Id
FROM Invoice
LEFT JOIN Persons
ON Persons.P_Id=Invoice.P_Id
Thank you for watching. Always your ideas are welcome.
Happy coding!
13 Awesome Zombie Artworks from Deviantart
Hey, everyone! So Halloween is just around the corner, and to celebrate this coming occasion, I give you... ZOMBIES!!! Enjoy! :)
Zombie Survival Guide - GN by *IbraimRoberson on deviantART
zombie by ~czarnystefan on deviantART
Zombie by ~Xythanon on deviantART
scream zombie by ~blow-engine on deviantART
Zombie apocalypse by ~korintic on deviantART
zombie boy by ~johnfsebastian on deviantART
Zombie by ~MrWizard44 on deviantART
Zombie Dude by ~DavidRapozaArt on deviantART
Zombie Eaters by *K-A-D-L on deviantART
Zombie Claire by ~someDude2 on deviantART
mother and zombie by ~the-wild-rover on deviantART
Zombie Apocalypse by ~GarthFT on deviantART
Zombie by ~artofneff on deviantART
Read more »
Zombie Survival Guide - GN by *IbraimRoberson on deviantART
zombie by ~czarnystefan on deviantART
Zombie by ~Xythanon on deviantART
scream zombie by ~blow-engine on deviantART
Zombie apocalypse by ~korintic on deviantART
zombie boy by ~johnfsebastian on deviantART
Zombie by ~MrWizard44 on deviantART
Zombie Dude by ~DavidRapozaArt on deviantART
Zombie Eaters by *K-A-D-L on deviantART
Zombie Claire by ~someDude2 on deviantART
mother and zombie by ~the-wild-rover on deviantART
Zombie Apocalypse by ~GarthFT on deviantART
Zombie by ~artofneff on deviantART
Subscribe to:
Posts (Atom)