private void updateSize() { Device device = mConfiguration.getDevice(); if (device == null) { return; } Screen screen = device.getDefaultHardware().getScreen(); if (screen == null) { return; } FolderConfiguration folderConfig = mConfiguration.getFullConfig(); ScreenOrientationQualifier qualifier = folderConfig.getScreenOrientationQualifier(); ScreenOrientation orientation = qualifier == null ? ScreenOrientation.PORTRAIT : qualifier.getValue(); // compute width and height to take orientation into account. int x = screen.getXDimension(); int y = screen.getYDimension(); int screenWidth, screenHeight; if (x > y) { if (orientation == ScreenOrientation.LANDSCAPE) { screenWidth = x; screenHeight = y; } else { screenWidth = y; screenHeight = x; } } else { if (orientation == ScreenOrientation.LANDSCAPE) { screenWidth = y; screenHeight = x; } else { screenWidth = x; screenHeight = y; } } int width = RenderPreviewManager.getMaxWidth(); int height = RenderPreviewManager.getMaxHeight(); if (screenWidth > 0) { double scale = getScale(screenWidth, screenHeight); width = (int) (screenWidth * scale); height = (int) (screenHeight * scale); } if (width != mWidth || height != mHeight) { mWidth = width; mHeight = height; Image thumbnail = mThumbnail; mThumbnail = null; if (thumbnail != null) { thumbnail.dispose(); } if (mHeight != 0) { mAspectRatio = mWidth / (double) mHeight; } } }
private static double getScale(int width, int height) { int maxWidth = RenderPreviewManager.getMaxWidth(); int maxHeight = RenderPreviewManager.getMaxHeight(); if (width > 0 && height > 0 && (width > maxWidth || height > maxHeight)) { if (width >= height) { // landscape return maxWidth / (double) width; } else { // portrait return maxHeight / (double) height; } } return 1.0; }
/** Determine whether this configuration has a better match in a different layout file */ private void updateForkStatus() { ConfigurationChooser chooser = mManager.getChooser(); FolderConfiguration config = mConfiguration.getFullConfig(); if (mAlternateInput != null && chooser.isBestMatchFor(mAlternateInput, config)) { return; } mAlternateInput = null; IFile editedFile = chooser.getEditedFile(); if (editedFile != null) { if (!chooser.isBestMatchFor(editedFile, config)) { ProjectResources resources = chooser.getResources(); if (resources != null) { ResourceFile best = resources.getMatchingFile(editedFile.getName(), ResourceType.LAYOUT, config); if (best != null) { IAbstractFile file = best.getFile(); if (file instanceof IFileWrapper) { mAlternateInput = ((IFileWrapper) file).getIFile(); } else if (file instanceof File) { mAlternateInput = AdtUtils.fileToIFile(((File) file)); } } } if (mAlternateInput != null) { mAlternateConfiguration = Configuration.create(mConfiguration, mAlternateInput); } } } }
/** * Sets whether the preview is visible. Previews that are off screen are typically marked * invisible during layout, which means we don't have to expend effort computing preview * thumbnails etc * * @param visible whether this preview is visible */ public void setVisible(boolean visible) { if (visible != mVisible) { mVisible = visible; if (mVisible) { if (mDirty != 0) { // Just made the render preview visible: configurationChanged(mDirty); // schedules render } else { updateForkStatus(); mManager.scheduleRender(this); } } else { dispose(); } } }
/** * Paints the preview title at the given position (and returns the required height) * * @param gc the graphics context to paint into * @param x the left edge of the preview rectangle * @param y the top edge of the preview rectangle * @param displayName the title string to be used */ int paintTitle(GC gc, int x, int y, boolean showFile, String displayName) { int titleHeight = 0; if (showFile && mIncludedWithin != null) { if (mManager.getMode() != INCLUDES) { displayName = "<include>"; } else { // Skip: just paint footer instead displayName = null; } } int width = getWidth(); int labelTop = y + 1; gc.setClipping(x, labelTop, width, 100); // Use font height rather than extent height since we want two adjacent // previews (which may have different display names and therefore end // up with slightly different extent heights) to have identical title // heights such that they are aligned identically int fontHeight = gc.getFontMetrics().getHeight(); if (displayName != null && displayName.length() > 0) { gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_WHITE)); Point extent = gc.textExtent(displayName); int labelLeft = Math.max(x, x + (width - extent.x) / 2); Image icon = null; Locale locale = mConfiguration.getLocale(); if (locale != null && (locale.hasLanguage() || locale.hasRegion()) && (!(mConfiguration instanceof NestedConfiguration) || ((NestedConfiguration) mConfiguration).isOverridingLocale())) { icon = locale.getFlagImage(); } if (icon != null) { int flagWidth = icon.getImageData().width; int flagHeight = icon.getImageData().height; labelLeft = Math.max(x + flagWidth / 2, labelLeft); gc.drawImage(icon, labelLeft - flagWidth / 2 - 1, labelTop); labelLeft += flagWidth / 2 + 1; gc.drawText(displayName, labelLeft, labelTop - (extent.y - flagHeight) / 2, true); } else { gc.drawText(displayName, labelLeft, labelTop, true); } labelTop += extent.y; titleHeight += fontHeight; } if (showFile && (mAlternateInput != null || mIncludedWithin != null)) { // Draw file flag, and parent folder name IFile file = mAlternateInput != null ? mAlternateInput : mIncludedWithin.getFile(); String fileName = file.getParent().getName() + File.separator + file.getName(); Point extent = gc.textExtent(fileName); Image icon = IconFactory.getInstance().getIcon("android_file"); // $NON-NLS-1$ int flagWidth = icon.getImageData().width; int flagHeight = icon.getImageData().height; int labelLeft = Math.max(x, x + (width - extent.x - flagWidth - 1) / 2); gc.drawImage(icon, labelLeft, labelTop); gc.setForeground(gc.getDevice().getSystemColor(SWT.COLOR_GRAY)); labelLeft += flagWidth + 1; labelTop -= (extent.y - flagHeight) / 2; gc.drawText(fileName, labelLeft, labelTop, true); titleHeight += Math.max(titleHeight, icon.getImageData().height); } gc.setClipping((Region) null); return titleHeight; }
/** * Handles clicks within the preview (x and y are positions relative within the preview * * @param x the x coordinate within the preview where the click occurred * @param y the y coordinate within the preview where the click occurred * @return true if this preview handled (and therefore consumed) the click */ public boolean click(int x, int y) { if (y >= mTitleHeight && y < mTitleHeight + HEADER_HEIGHT) { int left = 0; left += CLOSE_ICON_WIDTH; if (x <= left) { // Delete mManager.deletePreview(this); return true; } left += ZOOM_IN_ICON_WIDTH; if (x <= left) { // Zoom in mScale = mScale * (1 / 0.5); if (Math.abs(mScale - 1.0) < 0.0001) { mScale = 1.0; } render(0); mManager.layout(true); mCanvas.redraw(); return true; } left += ZOOM_OUT_ICON_WIDTH; if (x <= left) { // Zoom out mScale = mScale * (0.5 / 1); if (Math.abs(mScale - 1.0) < 0.0001) { mScale = 1.0; } render(0); mManager.layout(true); mCanvas.redraw(); return true; } left += EDIT_ICON_WIDTH; if (x <= left) { // Edit. For now, just rename InputDialog d = new InputDialog( AdtPlugin.getShell(), "Rename Preview", // title "Name:", getDisplayName(), null); if (d.open() == Window.OK) { String newName = d.getValue(); mConfiguration.setDisplayName(newName); if (mDescription != null) { mManager.rename(mDescription, newName); } mCanvas.redraw(); } return true; } // Clicked anywhere else on header // Perhaps open Edit dialog here? } mManager.switchTo(this); return true; }
/** * Returns the height of the preview, in pixels * * @return the height in pixels */ public int getHeight() { return (int) (mHeight * mScale * RenderPreviewManager.getScale()); }
/** * Returns the width of the preview, in pixels * * @return the width in pixels */ public int getWidth() { return (int) (mWidth * mScale * RenderPreviewManager.getScale()); }
/** * Creates a new {@linkplain RenderPreview} * * @param manager the manager * @param configuration the associated configuration * @return a new configuration */ @NonNull public static RenderPreview create( @NonNull RenderPreviewManager manager, @NonNull Configuration configuration) { LayoutCanvas canvas = manager.getCanvas(); return new RenderPreview(manager, canvas, configuration); }
/** * Notifies that the preview's configuration has changed. * * @param flags the change flags, a bitmask corresponding to the {@code CHANGE_} constants in * {@link ConfigurationClient} */ public void configurationChanged(int flags) { if (!mVisible) { mDirty |= flags; return; } if ((flags & MASK_RENDERING) != 0) { mResourceResolver.clear(); // Handle inheritance mConfiguration.syncFolderConfig(); updateForkStatus(); updateSize(); } // Sanity check to make sure things are working correctly if (DEBUG) { RenderPreviewMode mode = mManager.getMode(); if (mode == DEFAULT) { assert mConfiguration instanceof VaryingConfiguration; VaryingConfiguration config = (VaryingConfiguration) mConfiguration; int alternateFlags = config.getAlternateFlags(); switch (alternateFlags) { case Configuration.CFG_DEVICE_STATE: { State configState = config.getDeviceState(); State chooserState = mManager.getChooser().getConfiguration().getDeviceState(); assert configState != null && chooserState != null; assert !configState.getName().equals(chooserState.getName()) : configState.toString() + ':' + chooserState; Device configDevice = config.getDevice(); Device chooserDevice = mManager.getChooser().getConfiguration().getDevice(); assert configDevice != null && chooserDevice != null; assert configDevice == chooserDevice : configDevice.toString() + ':' + chooserDevice; break; } case Configuration.CFG_DEVICE: { Device configDevice = config.getDevice(); Device chooserDevice = mManager.getChooser().getConfiguration().getDevice(); assert configDevice != null && chooserDevice != null; assert configDevice != chooserDevice : configDevice.toString() + ':' + chooserDevice; State configState = config.getDeviceState(); State chooserState = mManager.getChooser().getConfiguration().getDeviceState(); assert configState != null && chooserState != null; assert configState.getName().equals(chooserState.getName()) : configState.toString() + ':' + chooserState; break; } case Configuration.CFG_LOCALE: { Locale configLocale = config.getLocale(); Locale chooserLocale = mManager.getChooser().getConfiguration().getLocale(); assert configLocale != null && chooserLocale != null; assert configLocale != chooserLocale : configLocale.toString() + ':' + chooserLocale; break; } default: { // Some other type of override I didn't anticipate assert false : alternateFlags; } } } } mDirty = 0; mManager.scheduleRender(this); }