Color of animated ActionBarDrawerToggle in ActionBar - android-5.0-lollipop

How can i change the color of animated ActionBarDrawerToggle icons in ActionBar, using AppCompat-v7 (v21)?
I tried this, but doesn't work. Thanks.
myActionBarActivity.java
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mLeftDrawer = (LinearLayout) findViewById(R.id.left_drawer);
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
R.string.drawer_open, R.string.drawer_close)
values/styles.xml
<item name="drawerArrowStyle">#style/DrawerArrowStyle</item>
<style name="DrawerArrowStyle" parent="Widget.AppCompat.DrawerArrowToggle">
<item name="spinBars">true</item>
<item name="color">#android:color/black</item>
</style>
UPDATE: solved, there was this entry <item name="actionBarWidgetTheme"> in my theme which probably overlapped <item name="drawerArrowStyle">. I removed it and now all works.

This should work..
<style name="DrawerArrowStyle" parent="Widget.AppCompat.DrawerArrowToggle">
<item name="spinBars">true</item>
<item name="color">#color/your_color</item>
</style>
and in your parent theme..
<style name="AppTheme" parent="AppBaseTheme">
<item name="drawerArrowStyle">#style/DrawerArrowStyle</item>
.
.
.
</style>

Since support library 24.1.0 you can now have access to getDrawerArrowDrawable(). So to change the color you just need to do this:
toggle.getDrawerArrowDrawable().setColor(getColor(R.color.colorPrimary));

There is a way to do it programmatically as well, by taking advantage of the existing color methods in DrawerArrowDrawable. You just need to pass your own DrawerArrowDrawable to ActionBarDrawerToggle and keep a reference to the DrawerArrowDrawable so you can call its methods.
However, that constructor within ActionBarDrawerToggle currently has package-private access, so you need to add a class in the android.support.v7.app package to gain access to it.
Here's an approach that extends from ActionBarDrawerToggle to expose the color methods.
Place this class into /src/android/support/v7/app/:
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.support.v7.app;
import android.app.ActionBar;
import android.app.Activity;
import android.content.Context;
import android.graphics.ColorFilter;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.ColorInt;
import android.support.annotation.StringRes;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.graphics.drawable.DrawerArrowDrawable;
import android.support.v7.widget.Toolbar;
import android.util.Log;
/*
* Version of ActionBarDrawerToggle that exposes DrawerArrowDrawable's color methods.
* Needs to be in android.support.v7.app in order to access a constructor in ActionBarDrawerToggle
* which currently has package-private access.
*/
public class ColorableActionBarDrawerToggle extends ActionBarDrawerToggle {
private final DrawerArrowDrawable mSlider;
/**
* Construct a new ColorableActionBarDrawerToggle.
*
* <p>The given {#link Activity} will be linked to the specified {#link DrawerLayout} and
* its Actionbar's Up button will be set to a custom drawable.
* <p>This drawable shows a Hamburger icon when drawer is closed and an arrow when drawer
* is open. It animates between these two states as the drawer opens.</p>
*
* <p>String resources must be provided to describe the open/close drawer actions for
* accessibility services.</p>
*
* #param activity The Activity hosting the drawer. Should have an ActionBar.
* #param drawerLayout The DrawerLayout to link to the given Activity's ActionBar
* #param openDrawerContentDescRes A String resource to describe the "open drawer" action
* for accessibility
* #param closeDrawerContentDescRes A String resource to describe the "close drawer" action
* for accessibility
*/
public ColorableActionBarDrawerToggle( Activity activity
, DrawerLayout drawerLayout
, #StringRes int openDrawerContentDescRes
, #StringRes int closeDrawerContentDescRes ) {
this(activity, null, drawerLayout, null, openDrawerContentDescRes, closeDrawerContentDescRes);
}
/**
* Construct a new ColorableActionBarDrawerToggle with a Toolbar.
* <p>
* The given {#link Activity} will be linked to the specified {#link DrawerLayout} and
* the Toolbar's navigation icon will be set to a custom drawable. Using this constructor
* will set Toolbar's navigation click listener to toggle the drawer when it is clicked.
* <p>
* This drawable shows a Hamburger icon when drawer is closed and an arrow when drawer
* is open. It animates between these two states as the drawer opens.
* <p>
* String resources must be provided to describe the open/close drawer actions for
* accessibility services.
* <p>
* Please use {#link #ActionBarDrawerToggle(Activity, DrawerLayout, int, int)} if you are
* setting the Toolbar as the ActionBar of your activity.
*
* #param activity The Activity hosting the drawer.
* #param toolbar The toolbar to use if you have an independent Toolbar.
* #param drawerLayout The DrawerLayout to link to the given Activity's ActionBar
* #param openDrawerContentDescRes A String resource to describe the "open drawer" action
* for accessibility
* #param closeDrawerContentDescRes A String resource to describe the "close drawer" action
* for accessibility
*/
public ColorableActionBarDrawerToggle( Activity activity
, DrawerLayout drawerLayout
, Toolbar toolbar
, #StringRes int openDrawerContentDescRes
, #StringRes int closeDrawerContentDescRes ) {
this(activity, toolbar, drawerLayout, null, openDrawerContentDescRes, closeDrawerContentDescRes);
}
/**
* In the future, [Google] can make this constructor public if [they] want to let developers customize
* the animation.
*
* [If they make this constructor public, ColorableActionBarDrawerToggle could be in another package.]
*/
<T extends DrawerArrowDrawable & DrawerToggle>
ColorableActionBarDrawerToggle( Activity activity
, Toolbar toolbar
, DrawerLayout drawerLayout
, T slider
, #StringRes int openDrawerContentDescRes
, #StringRes int closeDrawerContentDescRes ) {
super( activity
, toolbar
, drawerLayout
, (slider == null) ? slider = (T)new DrawerArrowDrawableToggle(activity, getActionBarThemedContext(activity, toolbar))
: slider
, openDrawerContentDescRes
, closeDrawerContentDescRes );
mSlider = slider;
}
/*
* Condensed (equivalent) version of the code in all the getActionBarThemedContext methods
* called by ActionBarDrawerToggle constructor as of 23.1.
*/
private static Context getActionBarThemedContext(Activity activity, Toolbar toolbar) {
Context context = null;
if (toolbar != null) {
context = toolbar.getContext();
} else if (activity instanceof DelegateProvider) { // Allow the Activity to provide an impl
final Delegate delegate = ((DelegateProvider) activity).getDrawerToggleDelegate();
context = delegate.getActionBarThemedContext();
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
final ActionBar actionBar = activity.getActionBar();
if (actionBar != null) {
context = actionBar.getThemedContext();
} else {
context = activity;
}
}
return context;
}
/// Expose DrawerArrowDrawable's color methods
public void setColorFilter(ColorFilter colorFilter) {
if(mSlider != null) {
mSlider.setColorFilter(colorFilter);
}
}
public void setColor(#ColorInt int color) {
if(mSlider != null) {
mSlider.setColor(color);
}
}
#ColorInt
public int getColor() {
if(mSlider != null) {
return mSlider.getColor();
}
return 0;//Color.TRANSPARENT;
}
public void setAlpha(int alpha) {
if(mSlider != null) {
mSlider.setAlpha(alpha);
}
}
}
Then just use ColorableActionBarDrawerToggle instead of ActionBarDrawerToggle, and call its setColor() or setColorFilter() methods to change the color at run time:
ColorableActionBarDrawerToggle mDrawerToggle;
// ....
mDrawerToggle.setColor(0xffff0000); // make it red

Related

Disable Tab in TabBar

I have a small problem which is hopefully nothing for you. :-)
I have a tabbar in mxml-Form. It looks like that:
<mx:TabBar id="tabBar_" itemClick="clickEvt(event);" selectedIndex="1" creationComplete="check()">
<mx:dataProvider>
<mx:Object label="Components" data="{ComponentTabOverview}"/>
<mx:Object label="Products" data="{ProductTabOverview}"/>
</mx:dataProvider>
</mx:TabBar>
Now I have the problem that I have to check after creating the tabbar, from which state the tabbar is created.
And if its created from an particular state, the first tab has to be disabled.
I did that as follows:
public function check():void {
if(checkstate_){
tabBar_.getChildAt(0).enabled= false;
}
}
Unfortunately it doesn't work.
Can somebody help me out?
Thanks!!!!
Mike
There seems to be an undocumented (it's marked #private in the ASDOCs) property in the NavBar component called enbaledField. The TabBar component extends NavBar at some point in it's class hierarchy.
Here is the code from the Apache Flex github repo (included just so you can read the ASDOC comments):
/**
* #private
* Storage for the enabled property.
*/
private var _enabledField:String = "enabled";
[Bindable("enabledFieldChanged")]
[Inspectable(category="Data")]
/**
* Name of the the field in the <code>dataProvider</code> object
* to use as the enabled label.
*
* #default "enabled"
*
* #langversion 3.0
* #playerversion Flash 11.1
* #playerversion AIR 3.4
* #productversion Flex 4.10
*/
public function get enabledField():String
{
return _enabledField;
}
So theoretically (I don't have Flex installed either), if the elements in your dataProvider have a property called enabled you can disable individual buttons in the TabBar.
Alternatively, if you'd like to use some other field in the dataProvider elements to indicate that the button should be enabled/disabled, you can set a new value on the enableField property.
The caveat seems to be that the ASDOC says this was first included in Flex 4.10. But I think that is odd since this is an older MX component. However, it could be that this property was indeed added in Flex 4.10.
If it's true, that this is only in Flex 4.10, then you could copy the respective bits of code and implement it yourself as #zeus suggested. In particular make note of the private method createNavChildren() in the NavBar class where the magic happens:
//Check for enabled field and assign it to the individual button if it exists.
if (_enabledField != "" && item.hasOwnProperty(_enabledField) == true)
{
navItem.enabled = Boolean(item[_enabledField]);
}
else
{
navItem.enabled = enabled;
}
Here is a link to NavBar class in the github repo that has all of the above code.

AS3 Error 1144: Method Implemented with Incompatible Signature

I'm working with the OSMF library REOPS [https://code.google.com/p/reops/]. Particularly the REOPS.zip project files. [https://code.google.com/p/reops/downloads/detail?name=REOPS.zip]
When trying to compile the RE_Skin_Compiled.fla, I receive the following error:
ClosedCaptionField.as, Line 14, Column 15 1144: Interface method get text in namespace com.realeyes.osmfplayer.controls:IClosedCaptionField is implemented with an incompatible signature in class com.realeyes.osmfplayer.controls:ClosedCaptionField.
This error is detailed by Adobe here: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/compilerErrors.html
Which states:
Method signatures must match exactly.
There are only two methods in the IClosedCaptionField interface, and they do match what is implemented in the ClosedCaptionField class.
IClosedCaptionField.as
package com.realeyes.osmfplayer.controls
{
import flash.text.TextFormat;
public interface IClosedCaptionField extends ISkinElementBase
{
function get text():String;
function set text(p_value:String):void;
}
}
ClosedCaptionField.as
package com.realeyes.osmfplayer.controls
{
import flash.text.TextField;
import flash.text.TextFormat;
/**
* Displays captions for media in the control bar. Accepts HTML
* text (limited by Flash HTML display). This component starts
* out invisible, and must be manually made visible.
*
* #author RealEyes Media
* #version 1.0
*/
public class ClosedCaptionField extends SkinElementBase implements IClosedCaptionField
{
public var cc_txt:TextField;
public function ClosedCaptionField()
{
super();
//start up hidden
//this.visible = false;
//text = "";
}
/**
* text
* The HTML text to display
*
* #return String
*/
public function get text():String
{
return cc_txt.htmlText;
}
public function set text(p_value:String):void
{
if (cc_txt)
{
cc_txt.htmlText = p_value;
}
trace("set cc text: " + p_value);
}
}
}
In the RE_Skin_compiled.fla Actionscript Settings, I have added the path to the REOPS\src\ folder, and it is able to find the classes when checking the properties on the AS Linkage.
Any ideas on what I might be missing in order to get the RE_Skin_Compiled.fla to correctly compile along with it's skin classes?
In the RE_Skin_compiled.fla, there is an included [underscore]code[underscore] compiled clip object which was causing the issues with conflicting classes.
After deleting the [underscore]code[underscore] compiled clip, the fla compiled with the linked classes correctly.

Zooming in JavaFx: ScrollEvent is consumed when content size exceeds ScrollPane viewport

I have an application that requires zoom inside a ScrollPane, but with my current approach I'm still facing 2 challenges. In order to replicate the problem, I have written a small application ZoomApp that you will find the code for underneath. Its' limited functionality allows zooming in and out (using Ctrl + Mouse Wheel) on some arbitrary shapes. When the zoomed content grows outside the bounds of the window, scroll bars should apperar.
Challenge 1.
When the scroll bars appears as a consequence of innerGroup scales up in size, the ScrollEvent no longer reach my ZoomHandler. Instead, we start scrolling down the window, until it reaches the bottom, when zooming again works as expect. I thought maybe
scrollPane.setPannable(false);
would make a difference, but no. How should this unwanted behaviour be avoided?
Challenge 2.
How would I go about to center innerGroup inside the scrollPane, without resorting to paint a pixel in the upper left corner of innerGroup with the desired delta to the squares?
As a sidenote, according to the JavaDoc for ScrollPane: "If an application wants the scrolling to be based on the visual bounds of the node (for scaled content etc.), they need to wrap the scroll node in a Group". This is the reason why I have an innerGroup and an outerGroup inside ScrollPane.
Any suggestions that guides me to the solution is much appreciated by this JavaFX novice.
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.SceneBuilder;
import javafx.scene.control.ScrollPane;
import javafx.scene.input.ScrollEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
/**
* Demo of a challenge I have with zooming inside a {#code ScrollPane}.
* <br>
* I am running JavaFx 2.2 on a Mac. {#code java -version} yields:
* <pre>
* java version "1.7.0_09"
* Java(TM) SE Runtime Environment (build 1.7.0_09-b05)
* Java HotSpot(TM) 64-Bit Server VM (build 23.5-b02, mixed mode)
* </pre>
* 6 rectangles are drawn, and can be zoomed in and out using either
* <pre>
* Ctrl + Mouse Wheel
* or Ctrl + 2 fingers on the pad.
* </pre>
* It reproduces a problem I experience inside an application I am writing.
* If you magnify to {#link #MAX_SCALE}, an interesting problem occurs when you try to zoom back to {#link #MIN_SCALE}. In the beginning
* you will see that the {#code scrollPane} scrolls and consumes the {#code ScrollEvent} until we have scrolled to the bottom of the window.
* Once the bottom of the window is reached, it behaves as expected (or at least as I was expecting).
*
* #author Skjalg Bjørndal
* #since 2012.11.05
*/
public class ZoomApp extends Application {
private static final int WINDOW_WIDTH = 800;
private static final int WINDOW_HEIGHT = 600;
private static final double MAX_SCALE = 2.5d;
private static final double MIN_SCALE = .5d;
private class ZoomHandler implements EventHandler<ScrollEvent> {
private Node nodeToZoom;
private ZoomHandler(Node nodeToZoom) {
this.nodeToZoom = nodeToZoom;
}
#Override
public void handle(ScrollEvent scrollEvent) {
if (scrollEvent.isControlDown()) {
final double scale = calculateScale(scrollEvent);
nodeToZoom.setScaleX(scale);
nodeToZoom.setScaleY(scale);
scrollEvent.consume();
}
}
private double calculateScale(ScrollEvent scrollEvent) {
double scale = nodeToZoom.getScaleX() + scrollEvent.getDeltaY() / 100;
if (scale <= MIN_SCALE) {
scale = MIN_SCALE;
} else if (scale >= MAX_SCALE) {
scale = MAX_SCALE;
}
return scale;
}
}
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
final Group innerGroup = createSixRectangles();
final Group outerGroup = new Group(innerGroup);
final ScrollPane scrollPane = new ScrollPane();
scrollPane.setContent(outerGroup);
scrollPane.setOnScroll(new ZoomHandler(innerGroup));
StackPane stackPane = new StackPane();
stackPane.getChildren().add(scrollPane);
Scene scene = SceneBuilder.create()
.width(WINDOW_WIDTH)
.height(WINDOW_HEIGHT)
.root(stackPane)
.build();
stage.setScene(scene);
stage.show();
}
private Group createSixRectangles() {
return new Group(
createRectangle(0, 0), createRectangle(110, 0), createRectangle(220, 0),
createRectangle(0, 110), createRectangle(110, 110), createRectangle(220, 110),
createRectangle(0, 220), createRectangle(110, 220), createRectangle(220, 220)
);
}
private Rectangle createRectangle(int x, int y) {
Rectangle rectangle = new Rectangle(x, y, 100, 100);
rectangle.setStroke(Color.ORANGERED);
rectangle.setFill(Color.ORANGE);
rectangle.setStrokeWidth(3d);
return rectangle;
}
}
OK, so I finally found a solution to my problem.
By merely substituting the line
scrollPane.setOnScroll(new ZoomHandler(innerGroup));
with
scrollPane.addEventFilter(ScrollEvent.ANY, new ZoomHandler(innerGroup));
it now works as expected. No mystic Rectangle or other hacks are needed.
So the next question is why? According to this excellent article on Processing Events,
An event filter is executed during the event capturing phase.
while
An event handler is executed during the event bubbling phase.
I assume this is what makes the difference.
The following workaround seems to be giving better results:
Set onscroll event on the outer group to steal the event from the scroll pane.
Add a opaque rectangle which covers the whole screen, so that you don't miss the scroll event. Apparently you can miss scroll event if you don't hit a shape.
Rectangle opaque = new Rectangle(0,0,WINDOW_WIDTH,WINDOW_HEIGHT);
opaque.setOpacity( 0 );
outerGroup.getChildren().add( opaque );
outerGroup.setOnScroll(new ZoomHandler(innerGroup));
In my case I have updated the following line
if (scrollEvent.isControlDown()) {
with if (!scrollEvent.isConsumed()) {.... along with the change you have posted.... :)

Getting javascript error while using smart-gwt

I am using a combination of gwt and smart gwt. However i get the following eror whenever my page loads. please help me with fixing this. .
Please find the attached screenshot for the image of the popup error for the same
15:06:02.097 [ERROR] [detectfiles] 15:06:02.097:TMR5:WARN:Log:Error:
'Object required'
in /sc/modules/ISC_Core.js
at line 1782
[c]Element.getOffsetLeft(_1=>[DIVElement]{ID:isc_0})
[c]Element.getOffset(_1=>"left", _2=>[ImgButton ID:isc_ImgButton_0], _3=>undef, _4=>false, _5=>true)
Canvas.getLeftOffset(_1=>undef)
Canvas.getPageLeft()
Canvas.$414(null, undef)
[c]Page.handleEvent(_1=>null, _2=>"resize", _3=>undef)
[c]EventHandler.$78p(_1=>"landscape")
[c]EventHandler.$hr(_1=>undef)
callback(undefined=>undef)
"isc.EH.$hr()"
[c]Class.fireCallback(_1=>"isc.EH.$hr()", _2=>undef, _3=>Array[0], _4=>Obj{length:2}, _5=>true) on [Class Timer]
[c]Timer.$in(_1=>"$ir28")
anonymous()
"isc.Timer.$in('$ir28')"
com.smartgwt.client.core.JsObject$SGWT_WARN: 15:06:02.097:TMR5:WARN:Log:Error:
'Object required'
in /sc/modules/ISC_Core.js
at line 1782
[c]Element.getOffsetLeft(_1=>[DIVElement]{ID:isc_0})
[c]Element.getOffset(_1=>"left", _2=>[ImgButton ID:isc_ImgButton_0], _3=>undef, _4=>false, _5=>true)
Canvas.getLeftOffset(_1=>undef)
Canvas.getPageLeft()
Canvas.$414(null, undef)
[c]Page.handleEvent(_1=>null, _2=>"resize", _3=>undef)
[c]EventHandler.$78p(_1=>"landscape")
[c]EventHandler.$hr(_1=>undef)
callback(undefined=>undef)
"isc.EH.$hr()"
[c]Class.fireCallback(_1=>"isc.EH.$hr()", _2=>undef, _3=>Array[0], _4=>Obj{length:2}, _5=>true) on [Class Timer]
[c]Timer.$in(_1=>"$ir28")
anonymous()
"isc.Timer.$in('$ir28')"
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:105)
at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)
at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessages(BrowserChannelServer.java:292)
at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:546)
at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:363)
at java.lang.Thread.run(Thread.java:662)
Here is a piece of code in which I am using TreeGrid inside a popup
private PopupPanel createConsoPopup() {
final PopupPanel consoPopup = new PopupPanel();
consoPopup.setAnimationEnabled(true);
consoPopup.setAutoHideEnabled(true);
VerticalPanel consoContent = new VerticalPanel();
VEPConsoTree consoTree = new VEPConsoTree(lineTreeNode, vepConsoTree);
vepConsoTree = consoTree.getCheckStationTree();
vepConsoTree.addSelectionChangedHandler(new SelectionChangedHandler() {
#Override
public void onSelectionChanged(SelectionEvent event) {
((TextBox)flexTable.getWidget(selectedRowNum, 0)).setText(vepConsoTree.getSelectedRecord().getAttribute("vepAreaName")+"_"+vepConsoTree.getSelectedRecord().getAttribute("checkStationName"));
consoPopup.hide();
}
});
consoContent.add(consoTree);
consoPopup.add(consoContent);
return consoPopup;
}
Following is my VEPConsoTree class:
package com.renault.veppwrstats.client;
import com.google.gwt.user.client.ui.Composite;
import com.smartgwt.client.types.TreeModelType;
import com.smartgwt.client.widgets.events.DrawEvent;
import com.smartgwt.client.widgets.events.DrawHandler;
import com.smartgwt.client.widgets.tree.Tree;
import com.smartgwt.client.widgets.tree.TreeGrid;
import com.smartgwt.client.widgets.tree.TreeNode;
public class VEPConsoTree extends Composite {
private TreeNode[] lineTreeNode;
private TreeGrid vepConsoTree;
//private DFConstantsForLocale constants = GWT.create(DFConstantsForLocale.class);
/**
* #param lineTreeNode
* #param vepConsoTree
*/
public VEPConsoTree(TreeNode[] lineTreeNode, TreeGrid vepConsoTree) {
super();
this.lineTreeNode = lineTreeNode;
this.vepConsoTree = vepConsoTree;
//Grid grid = chckStatRestrictPanel();
initWidget(vepConsoTree());
}
/**
* This function creates checkStation Restriction Panel(tree) along with
* Select/Unselect All button
*
* #return
*/
private TreeGrid vepConsoTree() {
return createTreeGrid();
}
/**
* This function creates CheckStation Restriction Tree
*
* #return {#link TreeGrid}
*/
private TreeGrid createTreeGrid() {
final TreeGrid chckTreeGrid = new TreeGrid();
chckTreeGrid.setHeight("269px");
chckTreeGrid.setWidth("250px");
chckTreeGrid.setData(createChkStationTree());
//chckTreeGrid.setSelectionAppearance(SelectionAppearance.CHECKBOX);
//chckTreeGrid.setShowPartialSelection(false);
//chckTreeGrid.setCascadeSelection(true);
chckTreeGrid.setFolderIcon(null);
chckTreeGrid.setNodeIcon(null);
chckTreeGrid.setShowConnectors(true);
chckTreeGrid.setShowHeader(false);
//addSelectionChangeHndler(chckTreeGrid);
chckTreeGrid.addDrawHandler(new DrawHandler() {
public void onDraw(DrawEvent event) {
chckTreeGrid.getTree().openAll();
}
});
vepConsoTree = chckTreeGrid;
return chckTreeGrid;
}
/**
* This function creates a basic tree
*/
private Tree createChkStationTree() {
Tree chckStationTree = new Tree();
chckStationTree.setModelType(TreeModelType.PARENT);
chckStationTree.setRootValue(1);
chckStationTree.setIdField("id");
chckStationTree.setOpenProperty("isOpen");
chckStationTree.setData(lineTreeNode);
chckStationTree.setParentIdField("parent");
return chckStationTree;
}
/**
* #return the vepConsoTree
*/
public final TreeGrid getCheckStationTree() {
return vepConsoTree;
}
/**
* #param vepConsoTree the vepConsoTree to set
*/
public final void setCheckStationTree(TreeGrid checkStationTree) {
this.vepConsoTree = checkStationTree;
}
/**
* #return the lineTreeNode
*/
public final TreeNode[] getLineTreeNode() {
return lineTreeNode;
}
/**
* #param lineTreeNode the lineTreeNode to set
*/
public final void setLineTreeNode(TreeNode[] lineTreeNode) {
this.lineTreeNode = lineTreeNode;
}
}
Short answer : don't mix GWT and SmartGWT when you can
Can I mix Smart GWT and GWT widgets?
Yes, with caveats.
Smart GWT has interoperability support that allows a Smart GWT widget
to be added to a GWT container and allows a GWT widget to be added to
a Smart GWT container, and it's appropriate to use this for:
incremental migration to Smart GWT, such as introducing singular,
sophisticated Smart GWT components like the Calendar or CubeGrid to an
existing GWT application
using sophisticated third-party GWT widgets within Smart GWT, where
Smart GWT doesn't have corresponding built-in functionality
However it does not make sense to freely intermix Smart GWT and GWT
(or other) components, that is, for example, you should not place GWT
widgets within a Smart GWT container that is in turn within a GWT
container. In general, don't intermix widgets unless the need for a
feature forces you to.
The reason for this is that there are limits to the maximum degree
that two Ajax widget kits (including GWT) can interoperate - there are
no standards that allow interoperability in the areas of management of
tab order, zIndex management, pixel-perfect layout, section 508
accessibility and multi-level modality.
Note that "bugs" reported when intermixing GWT and Smart GWT
inappropriately (that is, in contradiction to these guidelines) are
generally going to be marked WONTFIX, although we will revisit this in
the future if core GWT begins to support APIs that would allow better
interoperability.
If you really need to mix GWT and SmartGWT here are the guidelines from Isomorphic
Because Smart GWT's pixel-perfect layout and auto-sizing support goes
beyond the capabilities of simple CSS layout, components need to know
the actual pixel width they have been allocated by their parent
element; they cannot "flow into" an HTML element of unspecified size.
The issue here is that GWT's containers do not provide an API similar
to Smart GWT's Canvas.getInnerWidth(), which in Smart GWT can be used
by child components to find out the available space to draw themselves
in, and hence recursively lay out out their own children. Nor do GWT
containers fire events when they are resized, or when the available
width changes for various reasons (e.g. scrollbar(s) introduced, or
CSS style changes add borders and hence reduce space).
A lot of parent<->child coordination and signaling is required to
really create an extensible pixel-perfect layout system. Smart
GWT/SmartClient has implemented all the necessary hooks to allow a
third-party widget to be embedded inside a Canvas and participate in a
precise layout, but GWT is not there yet.
If you absolutely must place a Smart GWT interface inside a GWT
container and you want it to fill the container, the best approach is
to listen for a window-level resize event and run your own layout
calculations that ultimately call resizeTo() on your topmost Smart GWT
widget. All Smart GWT widgets nested under that topmost widget will
then handle layout normally.
NOTE: Don't bother trying to find a way to insert width:100% into
Smart GWT's rendered HTML, this won't work.
source : http://forums.smartclient.com/showthread.php?t=8159

Is there a way to clear out embedded Bitmap assets in AS3/AIR

first time posting on here.
I'm creating an AIR 3.0 app.
For a lot of my graphical assets I'm using the Flex embed metadata to embed bitmap objects as Classes and then instantiating them.
The problem is that it seems these never get garbage collected. I haven't found much info online but I've seen a couple of posts that seem to confirm this.
Anytime one of my classes gets instantiated that has these embedded assets, they always create new instances of the Bitmaps and BitmapDatas rather than reusing what's already in memory. This is a huge problem for memory. And I can't find any way of de-referenciong them or getting them to leave memory.
So the only solution I can think is to just load the graphics from disk rather than using the embed tag. But I'd rather not do this seeing as how when the app is packaged and installed, all of those graphcial assets will be on the end users computer rather than contained within the SWF.
Anyoen run into this? Have a solution? Or an alternate solution than the one I can think of?
Thanks!
Kyle
Well, I guess this is expected behaviour, because the new operator should always create new objects. But those new objects should get garbage collected, just the asset class will not, since it is a class.
You could build a cache that acts like a singleton factory. You request your image by specifying an id, the cache then either creates that image if it doesn't exist already, or just return the single instance if it does. It's been a while since I last coded ActionScript, so maybe you should take this as pseudo-code ;)
public class Cache {
import flash.utils.Dictionary;
import flash.utils.getDefinitionByName;
[Embed(source="example.gif")]
public static var ExampleGif:Class;
/**
* The single instance of the cache.
*/
private static var instance:Cache;
/**
* Gets the Cache instance.
*
* #return
* The Cache
*/
public static function getInstance():Cache {
if (Cache.instance == null) {
Cache.instance = new Cache();
}
return Cache.instance;
}
/**
* The cached assets are in here.
*/
private var dictionary:Dictionary
public function Chache() {
if (Cache.instance != null) {
throw new Error("Can not instanciate more than once.");
}
this.dictionary = new Dictionary();
}
/**
* Gets the single instantiated asset its name.
*
* #param assetName
* The name of the variable that was used to store the embeded class
*/
public function getAsset(assetName:String):Object {
if (this.dictionary[assetName] == null) {
var AssetClass = getDefinitionByName(assetName) as Class;
this.dictionary[assetName] = new AssetClass();
}
return this.dicionary[assetName];
}
}
You could then use it like this:
public class Example {
public static function main() {
Bitmap exampleGif1 = Cache.getInstance().getAsset("ExampleGif") as Bitmap;
Bitmap exampleGif2 = Cache.getInstance().getAsset("ExampleGif") as Bitmap;
trace("both should be the same instance: " + (exampleGif1 == exampleGif2));
}
}
I didn't test this, so let me know if it works.
I think what you're looking for is dispose() http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/BitmapData.html?#dispose()
If you decide to go with a caching system, here is a link with some code that is tested http://thanksmister.com/2009/01/29/flex-imagecache-a-cheap-way-to-cache-images/ . The link it has to another technique, using SuperImage, is broken, but I managed to find this http://demo.quietlyscheming.com/superImage/app.html .