1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.motorola.studio.android.emulator.skin.android.parser; 17 18 import java.io.File; 19 import java.util.Collection; 20 import java.util.Iterator; 21 import java.util.LinkedHashSet; 22 import java.util.LinkedList; 23 import java.util.List; 24 25 import org.eclipse.swt.graphics.ImageData; 26 import org.eclipse.swt.graphics.Point; 27 import org.eclipse.swt.graphics.RGB; 28 29 /** 30 * DESCRIPTION: 31 * This class represents a skin layout file 32 * 33 * RESPONSIBILITY: 34 * Represent all the contents of a skin layout file 35 * 36 * COLABORATORS: 37 * None. 38 * 39 * USAGE: 40 * Use the class public APIs to retrieve data of the skin 41 */ 42 public class LayoutFileModel 43 { 44 /** 45 * Event to rotate the screen 46 */ 47 private static final String ROTATE_SCREEN_EVENT = "EV_SW:0:0"; 48 49 /** 50 * Command to rotate the screen 51 */ 52 private static final String ROTATE_SCREEN_CMD = "5 0 0"; 53 54 /** 55 * Command to get the screen back to its default orientation 56 */ 57 private static final String RETURN_TO_DEFAULT_SCREEN_CMD = "5 0 1"; 58 59 /** 60 * A collection containing all layouts read from the layout file 61 */ 62 private Collection<LayoutBean> layouts; 63 64 /** 65 * A collection containing all parts read from the layout file 66 */ 67 private Collection<PartBean> parts = new LinkedHashSet<PartBean>(); 68 69 /** 70 * The keyboard charmap used by this skin 71 */ 72 private String keyboardCharmap; 73 74 /** 75 * The default network speed used by this skin 76 */ 77 private String networkSpeed; 78 79 /** 80 * The default network delay used by this skin 81 */ 82 private String networkDelay; 83 84 /** 85 * Sets the keyboard charmap used by this skin 86 * 87 * @param keyboardCharmap The keyboard charmap name 88 */ 89 void setKeyboardCharmap(String keyboardCharmap) 90 { 91 this.keyboardCharmap = keyboardCharmap; 92 } 93 94 /** 95 * Sets the default network speed used by this skin 96 * 97 * @param keyboardCharmap The default network speed used by this skin 98 */ 99 void setNetworkSpeed(String networkSpeed) 100 { 101 this.networkSpeed = networkSpeed; 102 } 103 104 /** 105 * Sets the default network delay of this skin 106 * 107 * @param The default network delay 108 */ 109 void setNetworkDelay(String networkDelay) 110 { 111 this.networkDelay = networkDelay; 112 } 113 114 /** 115 * Creates a new part, registers it and returns it to the user 116 * 117 * This version is used when the skin is simple, i.e. when there is a single 118 * part and no layouts defined. To support landscape/portrait rotation, we create 119 * "pseudo-layouts" at memory as well. 120 * 121 * @return The part 122 */ 123 PartBean newPart() 124 { 125 return newPart(PartBean.UNIQUE_PART); 126 } 127 128 /** 129 * Creates a new part, registers it and returns it to the user 130 * Use this version when the skin have multiple parts 131 * (i.e., if there is a "parts" element in the layout file) 132 * 133 * @param name The part name 134 * 135 * @return The part 136 */ 137 PartBean newPart(String name) 138 { 139 PartBean bean = new PartBean(name); 140 parts.add(bean); 141 return bean; 142 } 143 144 /** 145 * Creates a new layout, registers it and returns it to the user 146 * 147 * @param name The layout name 148 * 149 * @return The layout 150 */ 151 LayoutBean newLayout(String name) 152 { 153 LayoutBean bean = new LayoutBean(name); 154 if (layouts == null) 155 { 156 layouts = new LinkedHashSet<LayoutBean>(); 157 } 158 layouts.add(bean); 159 160 return bean; 161 } 162 163 /** 164 * Retrieves the keyboard charmap used by this skin 165 * 166 * @return The keyboard charmap name 167 */ 168 public String getKeyboardCharmap() 169 { 170 return keyboardCharmap; 171 } 172 173 /** 174 * Retrieves the default network speed of this skin 175 * 176 * @return The default network speed 177 */ 178 public String getNetworkSpeed() 179 { 180 return networkSpeed; 181 } 182 183 /** 184 * Retrieves the default network delay of this skin 185 * 186 * @return The default network delay 187 */ 188 public String getNetworkDelay() 189 { 190 return networkDelay; 191 } 192 193 public List<String> getLayoutNames() 194 { 195 List<String> layoutNames = new LinkedList<String>(); 196 if (layouts != null) 197 { 198 for (LayoutBean bean : layouts) 199 { 200 layoutNames.add(bean.getName()); 201 } 202 } 203 204 return layoutNames; 205 } 206 207 public Collection<String> getPartNames() 208 { 209 Collection<String> partNames = new LinkedHashSet<String>(); 210 for (PartBean bean : parts) 211 { 212 partNames.add(bean.getName()); 213 } 214 215 return partNames; 216 } 217 218 public Collection<String> getLayoutPartNames(String layoutName) 219 { 220 Collection<String> layoutPartNames = new LinkedHashSet<String>(); 221 LayoutBean bean = getLayoutByName(layoutName); 222 if (bean != null) 223 { 224 Collection<PartRefBean> partRefs = bean.getPartRefs(); 225 if (partRefs != null) 226 { 227 for (PartRefBean aRef : partRefs) 228 { 229 layoutPartNames.add(aRef.getPartName()); 230 } 231 } 232 } 233 234 return layoutPartNames; 235 } 236 237 public Point getPartPositionAtLayout(String layoutName, String partName, File skinFilesPath) 238 { 239 Point partPosition = null; 240 241 LayoutBean bean = getLayoutByName(layoutName); 242 if (bean != null) 243 { 244 Collection<PartRefBean> partRefs = bean.getPartRefs(); 245 for (PartRefBean prBean : partRefs) 246 { 247 if (prBean.getPartName().equals(partName)) 248 { 249 int x = Integer.parseInt(prBean.getX()); 250 String yStr = prBean.getY(); 251 int y; 252 if (yStr == null) 253 { 254 y = getBackgroundWidth(partName, skinFilesPath); 255 } 256 else 257 { 258 y = Integer.parseInt(yStr); 259 } 260 261 partPosition = new Point(x, y); 262 break; 263 } 264 } 265 } 266 else 267 { 268 partPosition = new Point(0, 0); 269 } 270 271 return partPosition; 272 } 273 274 public int getPartRotationAtLayout(String layoutName, String partName) 275 { 276 int partRotation = 0; 277 278 LayoutBean bean = getLayoutByName(layoutName); 279 if (bean != null) 280 { 281 Collection<PartRefBean> partRefs = bean.getPartRefs(); 282 for (PartRefBean prBean : partRefs) 283 { 284 if (prBean.getPartName().equals(partName)) 285 { 286 String rotStr = prBean.getRotation(); 287 if (rotStr != null) 288 { 289 partRotation = Integer.parseInt(rotStr); 290 } 291 break; 292 } 293 } 294 } 295 296 return partRotation; 297 } 298 299 public int getDpadRotation(String layoutName) 300 { 301 int dPadRotation = 0; 302 LayoutBean bean = getLayoutByName(layoutName); 303 if (bean != null) 304 { 305 dPadRotation = bean.getDpadRotation(); 306 } 307 308 return dPadRotation; 309 } 310 311 public Collection<String> getButtonNames(String partName) 312 { 313 Collection<String> buttonNames = new LinkedHashSet<String>(); 314 315 PartBean bean = getPartByName(partName); 316 if (bean != null) 317 { 318 Collection<ImagePositionBean> buttons = bean.getButtons(); 319 if (buttons != null) 320 { 321 for (ImagePositionBean button : buttons) 322 { 323 buttonNames.add(button.getName()); 324 } 325 } 326 } 327 return buttonNames; 328 } 329 330 public int getLayoutWidth(String layoutName) 331 { 332 int width = 0; 333 LayoutBean layout = getLayoutByName(layoutName); 334 if (layout != null) 335 { 336 width = Integer.parseInt(layout.getWidth()); 337 } 338 339 return width; 340 } 341 342 public int getLayoutHeight(String layoutName) 343 { 344 int height = 0; 345 LayoutBean layout = getLayoutByName(layoutName); 346 if (layout != null) 347 { 348 height = Integer.parseInt(layout.getHeight()); 349 } 350 351 return height; 352 } 353 354 public RGB getLayoutColor(String layoutName, File skinFilesPath) 355 { 356 RGB color = null; 357 LayoutBean layout = getLayoutByName(layoutName); 358 if (layout != null) 359 { 360 color = layout.getColor(); 361 if (color == null) 362 { 363 String mainPart = getMainPartName(layoutName); 364 File image = getBackgroundImage(mainPart, skinFilesPath); 365 ImageData img = new ImageData(image.getAbsolutePath()); 366 int pixel = img.getPixel(0, 0); 367 color = img.palette.getRGB(pixel); 368 layout.setKeyValue(ILayoutConstants.LAYOUT_COLOR, 369 "0x" + Integer.toHexString(color.red) + Integer.toHexString(color.green) 370 + Integer.toHexString(color.blue)); 371 } 372 } 373 else 374 { 375 color = new RGB(255, 255, 255); 376 } 377 378 return color; 379 } 380 381 public String getLayoutEvent(String layoutName) 382 { 383 String event = ""; 384 LayoutBean layout = getLayoutByName(layoutName); 385 if (layout != null) 386 { 387 event = layout.getEvent(); 388 } 389 390 return event; 391 } 392 393 public String getLayoutSwitchCommand(String layoutName) 394 { 395 LayoutBean bean = getLayoutByName(layoutName); 396 String event = bean.getEvent(); 397 if (ROTATE_SCREEN_EVENT.equals(event)) 398 { 399 return ROTATE_SCREEN_CMD; 400 } 401 else 402 { 403 return RETURN_TO_DEFAULT_SCREEN_CMD; 404 } 405 } 406 407 public boolean isSwapWidthHeightNeededAtLayout(String layoutName) 408 { 409 return isSwapWidthHeightNeededAtLayout(layoutName, getMainPartName(layoutName)); 410 } 411 412 public boolean isSwapWidthHeightNeededAtLayout(String layoutName, String partName) 413 { 414 boolean isRotated = false; 415 if (partName != null) 416 { 417 int rotation = getPartRotationAtLayout(layoutName, partName); 418 isRotated = rotation % 2 != 0; 419 } 420 return isRotated; 421 } 422 423 public File getBackgroundImage(String partName, File skinFilesPath) 424 { 425 File backgroundFile = null; 426 PartBean part = getPartByName(partName); 427 if (part != null) 428 { 429 ImagePositionBean backgroundBean = part.getBackground(); 430 if (backgroundBean != null) 431 { 432 backgroundFile = 433 new File(skinFilesPath, backgroundBean.getImageLocation().getName()); 434 } 435 } 436 437 return backgroundFile; 438 } 439 440 public Point getBackgroundPosition(String partName) 441 { 442 Point bgPosition = null; 443 PartBean part = getPartByName(partName); 444 if (part != null) 445 { 446 ImagePositionBean bgBean = part.getBackground(); 447 String xStr = null; 448 String yStr = null; 449 if (bgBean != null) 450 { 451 452 xStr = bgBean.getXPos(); 453 yStr = bgBean.getYPos(); 454 } 455 456 if ((xStr != null) && (yStr != null)) 457 { 458 bgPosition = new Point(Integer.parseInt(xStr), Integer.parseInt(yStr)); 459 } 460 else 461 { 462 bgPosition = new Point(0, 0); 463 } 464 } 465 466 return bgPosition; 467 } 468 469 public int getBackgroundWidth(String partName, File skinFilesPath) 470 { 471 int width = -1; 472 PartBean part = getPartByName(partName); 473 if (part != null) 474 { 475 ImagePositionBean bgBean = part.getBackground(); 476 if (bgBean != null) 477 { 478 width = bgBean.getWidth(skinFilesPath); 479 } 480 } 481 482 return width; 483 } 484 485 public int getBackgroundHeight(String partName, File skinFilesPath) 486 { 487 int height = -1; 488 PartBean part = getPartByName(partName); 489 if (part != null) 490 { 491 ImagePositionBean bgBean = part.getBackground(); 492 if (bgBean != null) 493 { 494 height = bgBean.getHeight(skinFilesPath); 495 } 496 } 497 498 return height; 499 } 500 501 public File getButtonImage(String partName, String buttonName) 502 { 503 File buttonFile = null; 504 ImagePositionBean button = getButtonByName(partName, buttonName); 505 if (button != null) 506 { 507 buttonFile = button.getImageLocation(); 508 } 509 510 return buttonFile; 511 } 512 513 public Point getButtonPosition(String partName, String buttonName) 514 { 515 Point buttonPos = null; 516 ImagePositionBean button = getButtonByName(partName, buttonName); 517 if (button != null) 518 { 519 buttonPos = 520 new Point(Integer.parseInt(button.getXPos()), 521 Integer.parseInt(button.getYPos())); 522 } 523 524 return buttonPos; 525 } 526 527 public int getButtonWidth(String partName, String buttonName, File skinFilesPath) 528 { 529 int width = -1; 530 ImagePositionBean button = getButtonByName(partName, buttonName); 531 if (button != null) 532 { 533 width = button.getWidth(skinFilesPath); 534 } 535 536 return width; 537 } 538 539 public int getButtonHeight(String partName, String buttonName, File skinFilesPath) 540 { 541 int height = -1; 542 ImagePositionBean button = getButtonByName(partName, buttonName); 543 if (button != null) 544 { 545 height = button.getHeight(skinFilesPath); 546 } 547 548 return height; 549 } 550 551 public Point getDisplayPosition(String partName) 552 { 553 Point displayPos = null; 554 555 PartBean bean = getPartByName(partName); 556 if (bean != null) 557 { 558 RectangleBean dispBean = bean.getDisplay(); 559 displayPos = 560 new Point(Integer.parseInt(dispBean.getXPos()), Integer.parseInt(dispBean 561 .getYPos())); 562 } 563 564 return displayPos; 565 } 566 567 public int getDisplayWidth(String partName) 568 { 569 int width = -1; 570 571 PartBean bean = getPartByName(partName); 572 if (bean != null) 573 { 574 RectangleBean dispBean = bean.getDisplay(); 575 width = Integer.parseInt(dispBean.getWidth()); 576 } 577 578 return width; 579 } 580 581 public int getDisplayHeight(String partName) 582 { 583 int height = -1; 584 585 PartBean bean = getPartByName(partName); 586 if (bean != null) 587 { 588 RectangleBean dispBean = bean.getDisplay(); 589 height = Integer.parseInt(dispBean.getHeight()); 590 } 591 592 return height; 593 } 594 595 private LayoutBean getLayoutByName(String layoutName) 596 { 597 LayoutBean layoutToReturn = null; 598 599 if (layouts != null) 600 { 601 Iterator<LayoutBean> it = layouts.iterator(); 602 while (it.hasNext()) 603 { 604 LayoutBean bean = it.next(); 605 if (bean.getName().equals(layoutName)) 606 { 607 layoutToReturn = bean; 608 break; 609 } 610 } 611 } 612 613 return layoutToReturn; 614 } 615 616 public PartBean getPartByName(String partName) 617 { 618 PartBean partToReturn = null; 619 620 Iterator<PartBean> it = parts.iterator(); 621 while (it.hasNext()) 622 { 623 PartBean bean = it.next(); 624 if (bean.getName().equals(partName)) 625 { 626 partToReturn = bean; 627 break; 628 } 629 } 630 631 return partToReturn; 632 } 633 634 private ImagePositionBean getButtonByName(String partName, String buttonName) 635 { 636 ImagePositionBean buttonToReturn = null; 637 PartBean pBean = getPartByName(partName); 638 if (pBean != null) 639 { 640 Collection<ImagePositionBean> buttons = pBean.getButtons(); 641 if (buttons != null) 642 { 643 for (ImagePositionBean bBean : buttons) 644 { 645 if (bBean.getName().equals(buttonName)) 646 { 647 buttonToReturn = bBean; 648 break; 649 } 650 } 651 } 652 } 653 654 return buttonToReturn; 655 } 656 657 /** 658 * Retrieves a layout main part, i.e. the first part that contains a display 659 * In future releases, check if it is needed to change this concept of "main part" 660 * 661 * @param layoutName The layout which main part is to be discovered 662 * 663 * @return The name of the layout main part 664 */ 665 public String getMainPartName(String layoutName) 666 { 667 String mainPartName = null; 668 for (LayoutBean layout : layouts) 669 { 670 if (layout.getName().equals(layoutName)) 671 { 672 Collection<PartRefBean> allRefs = layout.getPartRefs(); 673 for (PartRefBean partRef : allRefs) 674 { 675 String partName = partRef.getPartName(); 676 for (PartBean aPart : parts) 677 { 678 String aPartName = aPart.getName(); 679 if ((aPartName.equals(partName)) && (aPart.getDisplay() != null)) 680 { 681 mainPartName = aPartName; 682 break; 683 } 684 } 685 if (mainPartName != null) 686 { 687 break; 688 } 689 } 690 } 691 if (mainPartName != null) 692 { 693 break; 694 } 695 } 696 697 return mainPartName; 698 } 699 700 public boolean partHasBg(String partName) 701 { 702 PartBean part = getPartByName(partName); 703 ImagePositionBean background = part.getBackground(); 704 return background != null; 705 } 706 } 707