/*
* PinchScreen.java
*
* Copyright � 1998-2011 Research In Motion Limited
*
* 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.
*
* Note: For the sake of simplicity, this sample application may not leverage
* resource bundles and resource strings. However, it is STRONGLY recommended
* that application developers make use of the localization features available
* within the BlackBerry development platform to ensure a seamless application
* experience across a variety of languages and geographies. For more information
* on localizing your application, please refer to the BlackBerry Java Development
* Environment Development Guide associated with this release.
*/
package com.rim.samples.device.ui.picturescrollfielddemo;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.Display;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Screen;
import net.rim.device.api.ui.TouchEvent;
import net.rim.device.api.ui.TouchGesture;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.BitmapField;
import net.rim.device.api.ui.container.HorizontalFieldManager;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.container.VerticalFieldManager;
import net.rim.device.api.ui.input.InputSettings;
import net.rim.device.api.ui.input.TouchscreenSettings;
/**
* A screen to display an image which can be resized using pinch gestures
*/
public final class PinchScreen extends MainScreen {
private final Bitmap _bitmapOrig;
private final DemoBitmapField _bitmapField;
private final float _origWidth;
private final float _origHeight;
private float _previousWidth;
private float _previousHeight;
/**
* Creates a new PinchScreen object
*/
public PinchScreen(final Bitmap bitmap) {
super(NO_VERTICAL_SCROLL);
setTitle("Pinch Screen");
_origWidth = bitmap.getWidth();
_origHeight = bitmap.getHeight();
_previousWidth = _origWidth;
_previousHeight = _origHeight;
_bitmapOrig = bitmap;
_bitmapField = new DemoBitmapField(bitmap, FIELD_HCENTER);
// Center BitmapField using managers
final HorizontalFieldManager hfm =
new HorizontalFieldManager(USE_ALL_HEIGHT);
final VerticalFieldManager vfm =
new VerticalFieldManager(USE_ALL_WIDTH | FIELD_VCENTER);
vfm.add(_bitmapField);
hfm.add(vfm);
add(hfm);
// Enable pinch
final InputSettings inputSettings =
TouchscreenSettings.createEmptySet();
inputSettings.set(TouchscreenSettings.DETECT_PINCH, 1);
addInputSettings(inputSettings);
}
/**
* @see Screen#touchEvent(TouchEvent)
*/
protected boolean touchEvent(final TouchEvent message) {
if (message.getEvent() == TouchEvent.GESTURE) {
final TouchGesture gesture = message.getGesture();
final int event = gesture.getEvent();
final float magnitude = gesture.getPinchMagnitude();
if (event == TouchGesture.PINCH_UPDATE) {
onPinch(magnitude, false);
} else if (event == TouchGesture.PINCH_END) {
onPinch(magnitude, true);
}
}
return super.touchEvent(message);
}
/**
* Updates bitmap size on TouchGesture.PINCH_UPDATE or
* TouchGesture.PINCH_END
*
* @param magnitude
* Pinch magnitude of the current pinch gesture
* @param pinchEnd
* True if current gesture event is TouchGesture.PINCH_END,
* otherwise false
*/
private void onPinch(final float magnitude, final boolean pinchEnd) {
// Calculate dimensions, restrict to screen size
float width = Math.min(_previousWidth * magnitude, Display.getWidth());
float height =
Math.min(_previousHeight * magnitude, Display.getHeight());
// Maintain aspect ratio when either width or height is maxed out
if (width == Display.getWidth() || height == Display.getHeight()) {
float ratioWidth = 1f;
float ratioHeight = 1f;
ratioWidth = width / _previousWidth;
ratioHeight = height / _previousHeight;
if (ratioWidth < ratioHeight) {
height = _previousHeight * ratioWidth;
} else if (ratioHeight < ratioWidth) {
width = _previousWidth * ratioHeight;
}
}
// Ensure Bitmap will be at least original size
width = Math.max(width, _origWidth);
height = Math.max(height, _origHeight);
// Create Bitmap from original scaled to new calculated dimensions
final Bitmap bitmapScaled = new Bitmap((int) width, (int) height);
_bitmapOrig.scaleInto(bitmapScaled, Bitmap.FILTER_BOX);
// Replace Bitmap
_bitmapField.setBitmap(bitmapScaled);
// Save current dimensions
if (pinchEnd) {
_previousWidth = width;
_previousHeight = height;
}
}
/**
* A BitmapField class that resizes itself based on device orientation
*/
private final class DemoBitmapField extends BitmapField {
/**
* Creates a new DemoBitmapField object
*
* @param bitmap
* The Bitmap to be contained by this field
* @param style
* Style bit for this field
*/
DemoBitmapField(final Bitmap bitmap, final long style) {
super(bitmap, style);
}
/**
* @see Field#layout(int, int)
*/
protected void layout(final int width, final int height) {
final float displayWidth = Display.getWidth();
final float displayHeight = Display.getHeight();
float newWidth = width;
float newHeight = height;
if (displayWidth < _previousWidth
|| displayHeight < _previousHeight) {
float ratioWidth = 1;
float ratioHeight = 1;
ratioWidth = displayWidth / _previousWidth;
ratioHeight = displayHeight / _previousHeight;
if (ratioWidth < ratioHeight) {
newHeight = _previousHeight * ratioWidth;
} else if (ratioHeight < ratioWidth) {
newWidth = _previousWidth * ratioHeight;
}
// Create Bitmap from original scaled to new calculated
// dimensions
final Bitmap bitmapScaled =
new Bitmap((int) newWidth, (int) newHeight);
_bitmapOrig.scaleInto(bitmapScaled, Bitmap.FILTER_BOX);
// Need to use invokeLater() as bitmap cannot be set while
// in layout().
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
_bitmapField.setBitmap(bitmapScaled);
}
});
_previousWidth = newWidth;
_previousHeight = newHeight;
}
setExtent((int) newWidth, (int) newHeight);
super.layout((int) newWidth, (int) newHeight);
}
}
}