| /* |
| * Copyright (C) 2013 The Android Open Source Project |
| * |
| * 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 com.android.tools.idea.rendering.multi; |
| |
| import com.android.tools.idea.configurations.RenderContext; |
| import org.jetbrains.annotations.NotNull; |
| |
| import java.awt.*; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| |
| import static com.android.tools.idea.rendering.ShadowPainter.SHADOW_SIZE; |
| import static com.android.tools.idea.rendering.multi.RenderPreviewManager.HORIZONTAL_GAP; |
| import static com.android.tools.idea.rendering.multi.RenderPreviewManager.VERTICAL_GAP; |
| |
| /** |
| * Regular row layout for render previews |
| */ |
| public class PreviewBinPackingLayout { |
| private final @NotNull List<RenderPreview> myPreviews; |
| private final @NotNull RenderContext myRenderContext; |
| private final int myX; |
| private final int myY; |
| @SuppressWarnings("UnusedDeclaration") |
| private BinPacker myPacker; // Debug only |
| |
| public PreviewBinPackingLayout(@NotNull List<RenderPreview> previews, @NotNull RenderContext renderContext, int x, int y) { |
| myPreviews = previews; |
| myRenderContext = renderContext; |
| myX = x; |
| myY = y; |
| } |
| |
| private int myLayoutHeight; |
| |
| public boolean performLayout() { |
| Rectangle clientArea = myRenderContext.getClientArea(); |
| Dimension scaledImageSize = myRenderContext.getScaledImageSize(); |
| int scaledImageWidth = scaledImageSize.width; |
| int scaledImageHeight = scaledImageSize.height; |
| |
| int availableWidth = clientArea.x + clientArea.width - myX; |
| int availableHeight = clientArea.y + clientArea.height - myY; |
| int maxVisibleY = clientArea.y + clientArea.height; |
| int bottomBorder = scaledImageHeight + SHADOW_SIZE; |
| int rightHandSide = scaledImageWidth + HORIZONTAL_GAP + SHADOW_SIZE; |
| |
| int minWidth = Integer.MAX_VALUE; |
| int minHeight = Integer.MAX_VALUE; |
| for (RenderPreview preview : myPreviews) { |
| minWidth = Math.min(minWidth, preview.getLayoutWidth()); |
| minHeight = Math.min(minHeight, preview.getLayoutHeight()); |
| } |
| |
| BinPacker packer = new BinPacker(minWidth, minHeight); |
| if (BinPacker.DEBUG) { |
| myPacker = null; |
| } |
| |
| // TODO: Instead of this, just start with client area and occupy scaled image size! |
| |
| // Add in gap on right and bottom since we'll add that requirement on the width and |
| // height rectangles too (for spacing) |
| packer.addSpace(new Rectangle(rightHandSide, 0, availableWidth - rightHandSide + HORIZONTAL_GAP, availableHeight + VERTICAL_GAP)); |
| if (maxVisibleY > bottomBorder) { |
| packer.addSpace(new Rectangle(0, bottomBorder + VERTICAL_GAP, availableWidth + HORIZONTAL_GAP, |
| maxVisibleY - bottomBorder + VERTICAL_GAP)); |
| } |
| |
| // TODO: Sort previews first before attempting to position them? |
| |
| ArrayList<RenderPreview> aspectOrder = new ArrayList<RenderPreview>(myPreviews); |
| Collections.sort(aspectOrder, RenderPreview.INCREASING_ASPECT_RATIO); |
| |
| if (BinPacker.DEBUG) { |
| packer.dumpDiagnostics(); |
| } |
| |
| for (RenderPreview preview : aspectOrder) { |
| int previewWidth = preview.getLayoutWidth(); |
| int previewHeight = preview.getLayoutHeight(); |
| previewHeight += VERTICAL_GAP; |
| if (preview.isForked()) { |
| previewHeight += VERTICAL_GAP; |
| } |
| previewWidth += HORIZONTAL_GAP; |
| // title height? how do I account for that? |
| Rectangle position = packer.occupy(previewWidth, previewHeight); |
| if (position != null) { |
| preview.setPosition(position.x, position.y); |
| preview.setVisible(true); |
| |
| if (BinPacker.DEBUG) { |
| myPacker = packer; |
| } |
| } |
| else { |
| // Can't fit: give up |
| return false; |
| } |
| } |
| |
| myLayoutHeight = availableHeight; |
| return true; |
| } |
| |
| public int getLayoutHeight() { |
| return myLayoutHeight; |
| } |
| } |