/** * Copyright 2012 Neurowork Consulting S.L. * * This file is part of eMobc. * * CreateMenus.java * eMobc Android Framework * * eMobc is free software: you can redistribute it and/or modify * it under the terms of the Affero GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * eMobc is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the Affero GNU General Public License * along with eMobc. If not, see <http://www.gnu.org/licenses/>. * */ package com.emobc.android.menu; import java.io.Serializable; import java.util.List; import android.app.Activity; import android.content.Context; import android.content.pm.ActivityInfo; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.util.Log; import android.view.Display; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.TranslateAnimation; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import com.emobc.android.ApplicationData; import com.emobc.android.NextLevel; import com.emobc.android.activities.EMobcActivity; import com.emobc.android.activities.EMobcApplication; import com.emobc.android.activities.R; import com.emobc.android.menu.builders.HorizontalMenuBuilder; import com.emobc.android.menu.builders.MenuBuilder; import com.emobc.android.utils.ImagesUtils; import com.emobc.android.utils.InvalidFileException; import com.emobc.android.utils.Utils; /** * Class that contains the logic for create all menus of a screen depending on * the content of app.xml file * @author Jonatan Alcocer Luna * @version 0.1 * @since 0.1 */ public class CreateMenus extends EMobcActivity implements AnimationListener, Serializable { /** * */ private static final long serialVersionUID = -5139539241526551700L; private static final String ROTATION_LANDSCAPE = "landscape"; private static final String ROTATION_PORTRAIT = "portrait"; private static final String ROTATION_BOTH = "both"; private com.emobc.android.menu.Menu contextMenu; private boolean isEntryPoint; private LinearLayout sideMenuLayout; private RelativeLayout appLayout; private boolean menuOut = false; private AnimParams animParams = new AnimParams(); @Override protected void onDestroy(){ super.onDestroy(); //Unbind drawables from parent layout if (this.findViewById(R.id.parent)!=null){ unbindDrawables(this.findViewById(R.id.parent)); } } /** * Unbinds all drawables in a given view (and its child tree). * * @param findViewById Root view of the tree to unbind */ private void unbindDrawables(View view) { if (view.getBackground() != null) { view.getBackground().setCallback(null); } if (view instanceof ViewGroup) { for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) { unbindDrawables(((ViewGroup) view).getChildAt(i)); } try { ((ViewGroup) view).removeAllViews(); } catch(UnsupportedOperationException ignore) { //if can't remove all view (e.g. adapter view) - no problem } } } public static void createMenus(Activity activity, ApplicationData applicationData, NextLevel currentNextLevel){ int menuHeight = 0; //TOP MENU ViewGroup topLayout = (ViewGroup) activity.findViewById(R.id.topLayout); com.emobc.android.menu.Menu topMenu = applicationData.getTopMenu(currentNextLevel, activity); if(topLayout != null && topMenu != null) menuHeight += buildMenu(topLayout, topMenu, new HorizontalMenuBuilder(), activity); //BOTTOM MENU ViewGroup bottomLayout = (ViewGroup) activity.findViewById(R.id.bottomLayout); com.emobc.android.menu.Menu bottomMenu = applicationData.getBottomMenu(currentNextLevel, activity); if(bottomLayout != null && bottomMenu != null) menuHeight += buildMenu(bottomLayout, bottomMenu, new HorizontalMenuBuilder(), activity); //CONTEXT MENU if (activity instanceof CreateMenus) { CreateMenus createMenus = (CreateMenus) activity; createMenus.contextMenu = applicationData.getContextMenu(currentNextLevel, activity); } if(menuHeight > 0){ Display display = activity.getWindowManager().getDefaultDisplay(); int height = display.getHeight() - menuHeight; RelativeLayout contentLayout = (RelativeLayout)activity.findViewById(R.id.contentLayout); LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( android.widget.LinearLayout.LayoutParams.WRAP_CONTENT, height); contentLayout.setLayoutParams(lp); } //SIDE MENU // final String sideMenu = applicationData.getSideMenu(); // if(Utils.hasLength(sideMenu)){ // initializeSideMenuList(sideMenu); // } } /** * Creates each menu if is defined in app.xml file (if the field is empty * in app.xml file, simply ignore the creation.) * @param activity * @param isEntryPoint */ protected void createMenus(){ createMenus(this, getApplicationData(), getCurrentNextLevel()); } protected static int buildMenu(ViewGroup layout, com.emobc.android.menu.Menu menu, MenuBuilder menuBuilder, Activity activity) { // If no layout, noting to do. if(layout == null) return 0; // If no menu or menu builder is null, hide layout if(menu == null || menuBuilder == null){ layout.setVisibility(View.GONE); return 0; } return menuBuilder.buildMenu(activity, menu, layout); } // -- Context_Menu methods @Override public boolean onCreateOptionsMenu(Menu menu) { if(contextMenu != null){ createContextMenu(menu); return true; } Log.i("CreateMenus", "No existe menu contextual"); return false; } @Override public boolean onOptionsItemSelected(MenuItem item) { int selection = item.getItemId(); if(selection >= 0 && selection < this.contextMenu.getItems().size()){ com.emobc.android.menu.MenuItem itemSelected = this.contextMenu.getItems().get(selection); if(itemSelected != null){ itemSelected.executeMenuItem(this); return true; } } return false; } /** * Special method for creating the context menu. * Note: The context menu is a predefined menu of Android, so * that part of initializing the components to implement an * action is necessary to override the system selection methods. * @param contextMenu */ private void createContextMenu(Menu contextMenu) { if(this.contextMenu != null){ // Add Menu Items to Android Context Menu List<com.emobc.android.menu.MenuItem> items = this.contextMenu.getItems(); for(int i=0; i < items.size(); i++){ com.emobc.android.menu.MenuItem item = items.get(i); MenuItem menuItem = contextMenu.add(Menu.NONE, i, Menu.NONE, item.getTitle()); if(Utils.hasLength(item.getImageFileName())){ Drawable icon; try { icon = ImagesUtils.getDrawable(this, item.getImageFileName()); menuItem.setIcon(icon); } catch (InvalidFileException e) { Log.e("CreateMenus", e.getLocalizedMessage()); } } } } } // -- Side_Menu methods /** * Starts an animation to make room for SIDEMENU */ private void startAnimationMenu(){ CreateMenus me = CreateMenus.this; TextView menuHeader = (TextView) findViewById(R.id.MenuHeader); menuHeader.setText("SideMenu options"); Animation anim; int w = appLayout.getMeasuredWidth(); int h = appLayout.getMeasuredHeight(); int left = (int) (appLayout.getMeasuredWidth() * 0.8); if (!menuOut) {//OPEN SIDEMENU anim = new TranslateAnimation(0, left, 0, 0); sideMenuLayout.setVisibility(View.VISIBLE); animParams.init(left, 0, left + w, h); } else {//CLOSE SIDEMENU anim = new TranslateAnimation(0, -left, 0, 0); animParams.init(0, 0, w, h); } anim.setDuration(500); anim.setAnimationListener(me); // Only use fillEnabled and fillAfter if we don't call layout ourselves. // We need to do the layout ourselves and not use fillEnabled and fillAfter because when the anim is finished // although the View appears to have moved, it is actually just a drawing effect and the View hasn't moved. // Therefore clicking on the screen where the button appears does not work, but clicking where the View *was* does // work. // anim.setFillEnabled(true); // anim.setFillAfter(true); appLayout.startAnimation(anim); } @Override public void onAnimationEnd(Animation animation) { Log.v("CreateMenus", "onAnimationEnd"); menuOut = !menuOut; if (!menuOut) { sideMenuLayout.setVisibility(View.INVISIBLE); } appLayout.layout(animParams.left, animParams.top, animParams.right, animParams.bottom); } @Override public void onAnimationRepeat(Animation animation) { Log.v("CreateMenus", "onAnimationRepeat"); } @Override public void onAnimationStart(Animation animation) { Log.v("CreateMenus", "onAnimationStart"); } // -- onCreate @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TelephonyManager mTelephonyMgr = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE); mTelephonyMgr.listen(new TeleListener(), PhoneStateListener.LISTEN_CALL_STATE); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (!menuOut) { if ((keyCode == KeyEvent.KEYCODE_BACK)) { if(this.isEntryPoint!=true){ return super.onKeyDown(keyCode, event); }else{ moveTaskToBack(true); return true; } } }else{ startAnimationMenu(); } return false; } /** * Set activity rotation depending to field form app.xml file * Rotation types: landscape(horizontal), portrait (vertical), * both (horizontal|vertical) its determined by the sensor * @param activity */ public static void rotateScreen(Activity activity){ EMobcApplication app = (EMobcApplication)activity.getApplication(); ApplicationData applicationData = app.getApplicationData(); String rotation = applicationData.getRotation(); rotateScreen(activity, rotation); } /** * Set activity rotation depending to field form app.xml file * Rotation types: landscape(horizontal), portrait (vertical), * both (horizontal|vertical) its determined by the sensor * @param activity */ private static void rotateScreen(Activity activity, String rotation){ if(!Utils.hasLength(rotation)) return; if(ROTATION_BOTH.equals(rotation)){ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR); }else if(ROTATION_PORTRAIT.equals(rotation)){ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); }else if(ROTATION_LANDSCAPE.equals(rotation)){ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); }else{ Log.e("CreateMenus", "Rotation undefined: '"+rotation+"'"); rotateScreen(activity, ROTATION_BOTH);//Default } } /** * Show a banner in the activity with the information of his application Data item * If there is no information about the banner, it will not show */ public void createBanner(){ // try { // ApplicationData applicationData = SplashActivity.getApplicationData(); // BannerDataItem banner = applicationData.getBanner(); // if (banner!=null){ // LinearLayout bannerLayout; // // //Banner position // switch (banner.getPosition()){ // case BannerDataItem.TOP : // bannerLayout = (LinearLayout) findViewById(R.id.bannerTopLayout); // break; // case BannerDataItem.BOTTOM : // bannerLayout = (LinearLayout) findViewById(R.id.bannerBottomLayout); // break; // default: // bannerLayout = (LinearLayout) findViewById(R.id.bannerTopLayout); // } // // //Banner data // String id = banner.getId(); // // AdView adView = new AdView(this, AdSize.SMART_BANNER, id); // bannerLayout.addView(adView); // // AdRequest request = new AdRequest(); // // //Just for testing // request.addTestDevice(AdRequest.TEST_EMULATOR); // adView.loadAd(request); // // } // } catch (Exception e) { // Log.d("CreateBanner", "Error"); // } } public boolean isEntryPoint() { return isEntryPoint; } public void setEntryPoint(boolean isEntryPoint) { this.isEntryPoint = isEntryPoint; } /** * Class for intercept call phone. */ private class TeleListener extends PhoneStateListener implements Serializable { /** * */ private static final long serialVersionUID = 4505802614655221100L; public void onCallStateChanged(int state, String incomingNumber){ super.onCallStateChanged(state, incomingNumber); switch (state) { case TelephonyManager.CALL_STATE_IDLE: break; case TelephonyManager.CALL_STATE_OFFHOOK: break; case TelephonyManager.CALL_STATE_RINGING: break; default: break; } } } /** * Class that contains animation parameters */ static class AnimParams implements Serializable{ /** * */ private static final long serialVersionUID = 1L; int left, right, top, bottom; void init(int left, int top, int right, int bottom) { this.left = left; this.top = top; this.right = right; this.bottom = bottom; } } }