This class used DragLayer in the Android Launcher activity as a model. 33 | * It is a bit different in several respects: 34 | * (1) It extends MyAbsoluteLayout rather than FrameLayout; (2) it implements DragSource and DropTarget methods 35 | * that were done in a separate Workspace class in the Launcher. 36 | */ 37 | public class DragLayer extends MyAbsoluteLayout implements DragSource, DropTarget { 38 | private DragController mDragController; 39 | 40 | public DragLayer (Context context, AttributeSet attrs) { 41 | super(context, attrs); 42 | } 43 | @Override 44 | public boolean dispatchKeyEvent(KeyEvent event) { 45 | return mDragController.dispatchKeyEvent(event) || super.dispatchKeyEvent(event); 46 | } 47 | @Override 48 | public boolean onInterceptTouchEvent(MotionEvent ev) { 49 | return mDragController.onInterceptTouchEvent(ev); 50 | } 51 | @Override 52 | public boolean onTouchEvent(MotionEvent ev) { 53 | return mDragController.onTouchEvent(ev); 54 | } 55 | @Override 56 | public boolean dispatchUnhandledMove(View focused, int direction) { 57 | return mDragController.dispatchUnhandledMove(focused, direction); 58 | } 59 | 60 | // Interfaces of DragSource 61 | @Override 62 | public boolean allowDrag() { 63 | return true; 64 | } 65 | @Override 66 | public void setDragController(DragController controller) { 67 | mDragController = controller; 68 | } 69 | @Override 70 | public void onDropCompleted(View target, boolean success) { 71 | } 72 | 73 | // Interfaces of DropTarget 74 | @Override 75 | public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo) { 76 | final View v = (View)dragInfo; 77 | final int w = v.getWidth(); 78 | final int h = v.getHeight(); 79 | final int left = x - xOffset; 80 | final int top = y - yOffset; 81 | final DragLayer.LayoutParams lp = new DragLayer.LayoutParams (w, h, left, top); 82 | updateViewLayout(v, lp); 83 | } 84 | @Override 85 | public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo) { 86 | } 87 | @Override 88 | public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo) { 89 | } 90 | @Override 91 | public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo) { 92 | } 93 | @Override 94 | public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo) { 95 | return true; 96 | } 97 | @Override 98 | public Rect estimateDropLocation(DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo, Rect recycle) { 99 | return null; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /library/src/com/blahti/drag/DragListener.java: -------------------------------------------------------------------------------- 1 | package com.blahti.drag; 2 | 3 | /** 4 | * Interface to receive notifications when a drag starts or stops 5 | */ 6 | public interface DragListener { 7 | void onDragStart(DragSource source, Object info, DragController.DragBehavior dragBehavior); 8 | void onDragEnd(); 9 | } 10 | -------------------------------------------------------------------------------- /library/src/com/blahti/drag/DragSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a modified version of a class from the Android Open Source Project. 3 | * The original copyright and license information follows. 4 | * 5 | * Copyright (C) 2008 The Android Open Source Project 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | package com.blahti.drag; 21 | 22 | import android.view.View; 23 | 24 | /** 25 | * Interface defining an object where drag operations originate. 26 | * 27 | */ 28 | public interface DragSource { 29 | 30 | /** 31 | * This method is called to determine if the DragSource has something to drag. 32 | * 33 | * @return True if there is something to drag 34 | */ 35 | 36 | boolean allowDrag (); 37 | 38 | /** 39 | * This method is used to tell the DragSource which drag controller it is working with. 40 | * 41 | * @param dragger DragController 42 | */ 43 | 44 | void setDragController(DragController dragger); 45 | 46 | /** 47 | * This method is called on the completion of the drag operation so the DragSource knows 48 | * whether it succeeded or failed. 49 | * 50 | * @param target View - the view that accepted the dragged object 51 | * @param success boolean - true means that the object was dropped successfully 52 | */ 53 | 54 | void onDropCompleted (View target, boolean success); 55 | } 56 | -------------------------------------------------------------------------------- /library/src/com/blahti/drag/DragView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a modified version of a class from the Android Open Source Project. 3 | * The original copyright and license information follows. 4 | * 5 | * Copyright (C) 2008 The Android Open Source Project 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | package com.blahti.drag; 21 | 22 | import android.content.Context; 23 | import android.graphics.Bitmap; 24 | import android.graphics.Canvas; 25 | import android.graphics.Matrix; 26 | import android.graphics.Paint; 27 | import android.graphics.PixelFormat; 28 | import android.os.IBinder; 29 | import android.view.Gravity; 30 | import android.view.View; 31 | import android.view.ViewGroup; 32 | import android.view.WindowManager; 33 | 34 | /** 35 | * A DragView is a special view used by a DragController. During a drag operation, what is actually moving 36 | * on the screen is a DragView. A DragView is constructed using a bitmap of the view the user really 37 | * wants to move. 38 | * 39 | */ 40 | 41 | public class DragView extends View { 42 | private static final boolean DEBUG = false; 43 | private static final int PADDING_TO_SCALE = 0; 44 | private final int mRegistrationX; 45 | private final int mRegistrationY; 46 | private Bitmap mBitmap; 47 | private Paint mDebugPaint = new Paint(); 48 | private WindowManager.LayoutParams mLayoutParams; 49 | private WindowManager mWindowManager; 50 | 51 | public DragView(Context context) throws Exception { 52 | super(context); 53 | mRegistrationX = 0; 54 | mRegistrationY = 0; 55 | throw new Exception("DragView constructor permits only programatical calling"); 56 | } 57 | 58 | /** 59 | * Construct the drag view. 60 | *
61 | * The registration point is the point inside our view that the touch events should 62 | * be centered upon. 63 | * 64 | * @param context A context 65 | * @param bitmap The view that we're dragging around. We scale it up when we draw it. 66 | * @param registrationX The x coordinate of the registration point. 67 | * @param registrationY The y coordinate of the registration point. 68 | */ 69 | public DragView(Context context, Bitmap bitmap, int registrationX, int registrationY, int left, int top, int width, int height) { 70 | super(context); 71 | mWindowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); 72 | mRegistrationX = registrationX + (PADDING_TO_SCALE / 2); 73 | mRegistrationY = registrationY + (PADDING_TO_SCALE / 2); 74 | final float scaleFactor = ((float)width + PADDING_TO_SCALE) / (float)width; 75 | final Matrix scale = new Matrix(); 76 | scale.setScale(scaleFactor, scaleFactor); 77 | mBitmap = Bitmap.createBitmap(bitmap, left, top, width, height, scale, true); 78 | } 79 | 80 | @Override 81 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 82 | setMeasuredDimension(mBitmap.getWidth(), mBitmap.getHeight()); 83 | } 84 | @Override 85 | protected void onDraw(Canvas canvas) { 86 | if (DEBUG) { 87 | mDebugPaint.setStyle(Paint.Style.FILL); 88 | mDebugPaint.setColor(0x88dd0011); 89 | canvas.drawRect(0, 0, getWidth(), getHeight(), mDebugPaint); 90 | } 91 | canvas.drawBitmap(mBitmap, 0.0f, 0.0f, null); 92 | } 93 | @Override 94 | protected void onDetachedFromWindow() { 95 | super.onDetachedFromWindow(); 96 | mBitmap.recycle(); 97 | } 98 | 99 | void show(IBinder windowToken, int touchX, int touchY) { 100 | final WindowManager.LayoutParams lp = new WindowManager.LayoutParams( 101 | ViewGroup.LayoutParams.WRAP_CONTENT, 102 | ViewGroup.LayoutParams.WRAP_CONTENT, 103 | touchX - mRegistrationX, touchY - mRegistrationY, 104 | WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL, 105 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, 106 | PixelFormat.TRANSLUCENT 107 | ); 108 | lp.gravity = Gravity.LEFT | Gravity.TOP; 109 | lp.token = windowToken; 110 | lp.setTitle("DragView"); 111 | mLayoutParams = lp; 112 | mWindowManager.addView(this, lp); 113 | } 114 | void move(int touchX, int touchY) { 115 | WindowManager.LayoutParams lp = mLayoutParams; 116 | lp.x = touchX - mRegistrationX; 117 | lp.y = touchY - mRegistrationY; 118 | mWindowManager.updateViewLayout(this, lp); 119 | } 120 | void remove() { 121 | mWindowManager.removeView(this); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /library/src/com/blahti/drag/DropTarget.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a modified version of a class from the Android Open Source Project. 3 | * The original copyright and license information follows. 4 | * 5 | * Copyright (C) 2008 The Android Open Source Project 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | package com.blahti.drag; 21 | 22 | import android.graphics.Rect; 23 | 24 | /** 25 | * Interface defining an object that can receive a view at the end of a drag operation. 26 | * 27 | */ 28 | public interface DropTarget { 29 | 30 | /** 31 | * Handle an object being dropped on the DropTarget 32 | * 33 | * @param source DragSource where the drag started 34 | * @param x X coordinate of the drop location 35 | * @param y Y coordinate of the drop location 36 | * @param xOffset Horizontal offset with the object being dragged where the original 37 | * touch happened 38 | * @param yOffset Vertical offset with the object being dragged where the original 39 | * touch happened 40 | * @param dragView The DragView that's being dragged around on screen. 41 | * @param dragInfo Data associated with the object being dragged 42 | * 43 | */ 44 | void onDrop(DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo); 45 | 46 | void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo); 47 | 48 | void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo); 49 | 50 | void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo); 51 | 52 | /** 53 | * Check if a drop action can occur at, or near, the requested location. 54 | * This may be called repeatedly during a drag, so any calls should return 55 | * quickly. 56 | * 57 | * @param source DragSource where the drag started 58 | * @param x X coordinate of the drop location 59 | * @param y Y coordinate of the drop location 60 | * @param xOffset Horizontal offset with the object being dragged where the 61 | * original touch happened 62 | * @param yOffset Vertical offset with the object being dragged where the 63 | * original touch happened 64 | * @param dragView The DragView that's being dragged around on screen. 65 | * @param dragInfo Data associated with the object being dragged 66 | * @return True if the drop will be accepted, false otherwise. 67 | */ 68 | boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo); 69 | 70 | /** 71 | * Estimate the surface area where this object would land if dropped at the 72 | * given location. 73 | * 74 | * @param source DragSource where the drag started 75 | * @param x X coordinate of the drop location 76 | * @param y Y coordinate of the drop location 77 | * @param xOffset Horizontal offset with the object being dragged where the 78 | * original touch happened 79 | * @param yOffset Vertical offset with the object being dragged where the 80 | * original touch happened 81 | * @param dragView The DragView that's being dragged around on screen. 82 | * @param dragInfo Data associated with the object being dragged 83 | * @param recycle {@link Rect} object to be possibly recycled. 84 | * @return Estimated area that would be occupied if object was dropped at 85 | * the given location. Should return null if no estimate is found, 86 | * or if this target doesn't provide estimations. 87 | */ 88 | Rect estimateDropLocation(DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo, Rect recycle); 89 | 90 | // These methods are implemented in Views 91 | void getHitRect(Rect outRect); 92 | void getLocationOnScreen(int[] loc); 93 | int getLeft(); 94 | int getTop(); 95 | } 96 | -------------------------------------------------------------------------------- /library/src/com/blahti/drag/MyAbsoluteLayout.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a modified version of a class from the Android Open Source Project. 3 | * The original copyright and license information follows. 4 | * 5 | * Copyright (C) 2006 The Android Open Source Project 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | package com.blahti.drag; 21 | 22 | import android.content.Context; 23 | import android.util.AttributeSet; 24 | import android.view.View; 25 | import android.view.ViewGroup; 26 | import android.widget.RemoteViews.RemoteView; 27 | 28 | /** 29 | * A layout that lets you specify exact locations (x/y coordinates) of its 30 | * children. Absolute layouts are less flexible and harder to maintain than 31 | * other types of layouts without absolute positioning. 32 | * 33 | *
XML attributes
See {@link 34 | * android.R.styleable#ViewGroup ViewGroup Attributes}, {@link 35 | * android.R.styleable#View View Attributes}
36 | * 37 | *Note: This class is a clone of AbsoluteLayout, which is now deprecated. 38 | */ 39 | 40 | @RemoteView 41 | public class MyAbsoluteLayout extends ViewGroup { 42 | public MyAbsoluteLayout(Context context) { 43 | super(context); 44 | } 45 | 46 | public MyAbsoluteLayout(Context context, AttributeSet attrs) { 47 | super(context, attrs); 48 | } 49 | 50 | public MyAbsoluteLayout(Context context, AttributeSet attrs, 51 | int defStyle) { 52 | super(context, attrs, defStyle); 53 | } 54 | 55 | @Override 56 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 57 | int count = getChildCount(); 58 | 59 | int maxHeight = 0; 60 | int maxWidth = 0; 61 | 62 | // Find out how big everyone wants to be 63 | measureChildren(widthMeasureSpec, heightMeasureSpec); 64 | 65 | // Find rightmost and bottom-most child 66 | for (int i = 0; i < count; i++) { 67 | View child = getChildAt(i); 68 | if (child.getVisibility() != GONE) { 69 | int childRight; 70 | int childBottom; 71 | 72 | MyAbsoluteLayout.LayoutParams lp 73 | = (MyAbsoluteLayout.LayoutParams) child.getLayoutParams(); 74 | 75 | childRight = lp.x + child.getMeasuredWidth(); 76 | childBottom = lp.y + child.getMeasuredHeight(); 77 | 78 | maxWidth = Math.max(maxWidth, childRight); 79 | maxHeight = Math.max(maxHeight, childBottom); 80 | } 81 | } 82 | 83 | // Account for padding too 84 | maxWidth += getPaddingLeft () + getPaddingRight (); 85 | maxHeight += getPaddingTop () + getPaddingBottom (); 86 | /* original 87 | maxWidth += mPaddingLeft + mPaddingRight; 88 | maxHeight += mPaddingTop + mPaddingBottom; 89 | */ 90 | 91 | // Check against minimum height and width 92 | maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight()); 93 | maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth()); 94 | 95 | setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec), 96 | resolveSize(maxHeight, heightMeasureSpec)); 97 | } 98 | 99 | /** 100 | * Returns a set of layout parameters with a width of 101 | * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}, 102 | * a height of {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} 103 | * and with the coordinates (0, 0). 104 | */ 105 | @Override 106 | protected ViewGroup.LayoutParams generateDefaultLayoutParams() { 107 | return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 0, 0); 108 | } 109 | 110 | @Override 111 | protected void onLayout(boolean changed, int l, int t, 112 | int r, int b) { 113 | int count = getChildCount(); 114 | 115 | int paddingL = getPaddingLeft (); 116 | int paddingT = getPaddingTop (); 117 | for (int i = 0; i < count; i++) { 118 | View child = getChildAt(i); 119 | if (child.getVisibility() != GONE) { 120 | 121 | MyAbsoluteLayout.LayoutParams lp = 122 | (MyAbsoluteLayout.LayoutParams) child.getLayoutParams(); 123 | 124 | int childLeft = paddingL + lp.x; 125 | int childTop = paddingT + lp.y; 126 | /* 127 | int childLeft = mPaddingLeft + lp.x; 128 | int childTop = mPaddingTop + lp.y; 129 | */ 130 | child.layout(childLeft, childTop, 131 | childLeft + child.getMeasuredWidth(), 132 | childTop + child.getMeasuredHeight()); 133 | 134 | } 135 | } 136 | } 137 | 138 | @Override 139 | public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { 140 | return new MyAbsoluteLayout.LayoutParams(getContext(), attrs); 141 | } 142 | 143 | // Override to allow type-checking of LayoutParams. 144 | @Override 145 | protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { 146 | return p instanceof MyAbsoluteLayout.LayoutParams; 147 | } 148 | 149 | @Override 150 | protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { 151 | return new LayoutParams(p); 152 | } 153 | 154 | /** 155 | * Per-child layout information associated with MyAbsoluteLayout. 156 | * See 157 | * {@link android.R.styleable#MyAbsoluteLayout_Layout Absolute Layout Attributes} 158 | * for a list of all child view attributes that this class supports. 159 | */ 160 | public static class LayoutParams extends ViewGroup.LayoutParams { 161 | /** 162 | * The horizontal, or X, location of the child within the view group. 163 | */ 164 | public int x; 165 | /** 166 | * The vertical, or Y, location of the child within the view group. 167 | */ 168 | public int y; 169 | 170 | /** 171 | * Creates a new set of layout parameters with the specified width, 172 | * height and location. 173 | * 174 | * @param width the width, either {@link #MATCH_PARENT}, 175 | {@link #WRAP_CONTENT} or a fixed size in pixels 176 | * @param height the height, either {@link #MATCH_PARENT}, 177 | {@link #WRAP_CONTENT} or a fixed size in pixels 178 | * @param x the X location of the child 179 | * @param y the Y location of the child 180 | */ 181 | public LayoutParams(int width, int height, int x, int y) { 182 | super(width, height); 183 | this.x = x; 184 | this.y = y; 185 | } 186 | 187 | /** 188 | * Creates a new set of layout parameters. The values are extracted from 189 | * the supplied attributes set and context. The XML attributes mapped 190 | * to this set of layout parameters are: 191 | * 192 | *
layout_x
: the X location of the childlayout_y
: the Y location of the child15 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras pellentesque, dolor nec luctus ullamcorper, massa quam interdum metus, ac ultricies mauris risus nec purus. Fusce et nunc mi, ut consequat velit. Cras orci sapien, tincidunt sed iaculis ac, commodo sed neque. Sed gravida, quam id imperdiet venenatis, odio erat faucibus nisi, sed imperdiet velit nulla nec risus. Duis eget vehicula nibh. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec tincidunt, augue vitae feugiat cursus, nunc nunc volutpat ligula, ac molestie purus lectus sit amet mauris. Nunc nec felis tortor, a dignissim eros. Vivamus diam mauris, scelerisque molestie bibendum ut, dignissim quis neque. Aliquam ac turpis mi. Sed pretium interdum orci, sed semper lorem viverra id. Vivamus diam eros, convallis sit amet facilisis in, facilisis eget nibh. Aenean porttitor, neque nec ultrices laoreet, dolor metus cursus purus, non auctor lectus urna a enim. In nec lectus nunc, ac commodo arcu. Proin bibendum ligula non mi bibendum porta. Nam ac metus a magna tristique euismod eget vitae purus. 16 |
17 |18 | Vestibulum tincidunt, lectus at bibendum commodo, lectus velit commodo libero, et fermentum odio arcu sit amet dui. Quisque feugiat augue in erat scelerisque non mollis arcu facilisis. Nunc a dui sapien. Quisque quis nisi eu velit tincidunt placerat. Nunc vitae eros erat. Duis posuere diam ut orci adipiscing a ullamcorper est sollicitudin. Cras ipsum dolor, commodo viverra aliquet vel, pulvinar at sapien. Suspendisse eget justo et neque bibendum tempor. Morbi aliquet enim id arcu convallis cursus. Curabitur pellentesque condimentum dolor non sagittis. Ut tempor, erat in ullamcorper porta, purus erat tincidunt felis, ac auctor mauris libero nec purus. Praesent nisl justo, rutrum at rhoncus at, accumsan at mi. Fusce hendrerit imperdiet nulla a accumsan. Maecenas ut mi ac libero bibendum ullamcorper. 19 |
20 |21 | Nam ac est nunc. Suspendisse faucibus dictum lacus, sed tincidunt erat laoreet id. Cras leo dui, sodales vitae blandit quis, placerat in arcu. Nunc semper odio id dolor bibendum vel euismod sapien malesuada. Vestibulum metus purus, consequat sed varius ornare, feugiat ac lectus. Suspendisse consectetur ipsum a enim aliquet a pellentesque ipsum condimentum. Etiam molestie, augue id consectetur bibendum, tellus ante vestibulum tellus, vitae aliquam turpis ipsum et elit. Aenean ipsum ante, eleifend in mollis at, molestie ac augue. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec dui justo, consequat semper mollis sit amet, scelerisque vitae enim. Nullam nec odio et tortor sodales posuere. Mauris urna lorem, suscipit eu venenatis eu, consectetur ut purus. Vestibulum pharetra interdum convallis. Donec ac leo felis. 22 |
23 |24 | Mauris vulputate magna eget ligula fermentum eu molestie justo vulputate. Pellentesque condimentum, sem a sollicitudin luctus, lorem nunc dictum risus, a tincidunt tortor metus nec risus. Nunc ultricies consectetur accumsan. Etiam placerat aliquam tortor id lacinia. Vestibulum quis sem non urna venenatis condimentum. Vestibulum tempor sapien quam, et vulputate elit. Sed convallis mauris sed turpis elementum vitae pretium est tempus. Praesent congue viverra pharetra. Etiam accumsan congue sapien eu molestie. 25 |
26 |27 | Maecenas laoreet egestas tellus vestibulum gravida. Nulla rutrum dui at purus viverra et pretium diam fringilla. Sed nibh tortor, interdum ac egestas in, aliquam eu erat. Nunc convallis est posuere ipsum blandit luctus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur quam eros, hendrerit quis iaculis ut, rhoncus vel elit. Aenean sed ante et urna semper eleifend. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Morbi mollis lacus eu nulla vestibulum consectetur lobortis risus pretium. 28 |
29 |30 | Mauris scelerisque imperdiet venenatis. Suspendisse bibendum ullamcorper massa, vitae aliquam ligula sagittis at. Nullam rutrum justo nec tellus egestas eleifend. Suspendisse euismod quam in neque laoreet aliquam. Nunc non massa quis magna gravida ornare sed vitae tortor. Donec fringilla euismod accumsan. Mauris condimentum libero eget nisi sodales fringilla. 31 |
32 |33 | Suspendisse eget tellus nibh, eu accumsan nibh. Aenean a metus ut leo dapibus lacinia. Vestibulum vitae ante nec urna aliquet posuere sollicitudin vitae mauris. Pellentesque dapibus dapibus nisi, fringilla placerat metus aliquet id. Mauris imperdiet ornare tellus sed ornare. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus elementum fringilla molestie. Cras ac enim at libero condimentum eleifend. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; 34 |
35 |36 | Maecenas vel hendrerit massa. Maecenas quis augue turpis. Fusce scelerisque gravida nisl vitae auctor. Donec porta, diam id fringilla convallis, risus elit ultrices enim, nec auctor mi justo ut urna. Integer consectetur, sem sed molestie adipiscing, ligula lectus convallis nisl, eget pretium ante nulla non sem. Nulla magna metus, ornare at facilisis sit amet, ultrices id erat. Mauris gravida risus ac augue vulputate imperdiet porta tortor fringilla. Pellentesque cursus aliquam velit at mattis. Aliquam molestie fringilla urna, eget convallis sem hendrerit in. Cras pretium, nunc et aliquam ullamcorper, justo augue cursus turpis, vitae volutpat urna mi sit amet nulla. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 37 |
38 |39 | Donec iaculis aliquam nulla sodales sodales. Nunc quis egestas ipsum. Suspendisse accumsan tortor eu lacus sodales eu venenatis lectus varius. Vestibulum nisl mi, vulputate quis pulvinar eu, malesuada vitae dui. Ut eget nulla ipsum. Donec in risus laoreet arcu venenatis aliquam. Curabitur orci augue, pulvinar quis sollicitudin et, laoreet a turpis. Donec a nunc id elit volutpat euismod sed at lorem. 40 |
41 |42 | Phasellus arcu augue, rhoncus nec luctus quis, pharetra sit amet ante. Phasellus sed dui sit amet lacus auctor varius ac a arcu. Nullam eu congue ligula. Duis pretium nisi et tellus faucibus commodo. Vivamus dapibus imperdiet condimentum. Fusce at velit arcu, ac imperdiet mauris. Donec sit amet metus libero. Integer ac enim elit. Nulla quis erat urna. Morbi lobortis ligula vel sem placerat porttitor. Vestibulum in velit nulla, in malesuada sapien. Pellentesque sed sapien urna. Maecenas sodales felis sed nisl dictum euismod. Cras vitae sagittis elit. 43 |
44 |45 | あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。 46 |
47 |48 | またそのなかでいっしょになったたくさんのひとたち、ファゼーロとロザーロ、羊飼のミーロや、顔の赤いこどもたち、地主のテーモ、山猫博士のボーガント・デストゥパーゴなど、いまこの暗い巨きな石の建物のなかで考えていると、みんなむかし風のなつかしい青い幻燈のように思われます。では、わたくしはいつかの小さなみだしをつけながら、しずかにあの年のイーハトーヴォの五月から十月までを書きつけましょう。 49 |
50 | 51 | -------------------------------------------------------------------------------- /samples/demos/assets/css/sample.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 5px; 4 | } 5 | p::selection { 6 | background-color: #98d9f1; 7 | } -------------------------------------------------------------------------------- /samples/demos/assets/jpntext.js: -------------------------------------------------------------------------------- 1 | var jpntext = (function() { 2 | var global = { 3 | KIND: { 4 | 'mix': 0, 5 | 'ascii': 1, 6 | 'hira': 2, 7 | 'kata': 3, 8 | 'cjk': 4 9 | }, 10 | kind: function(text) { 11 | var result; 12 | if (global.isAscii(text)) { 13 | result = 'ascii'; 14 | } 15 | else if (global.isHiragana(text)) { 16 | result = 'hira'; 17 | } 18 | else if (global.isKatakana(text)) { 19 | result = 'kata'; 20 | } 21 | else if (global.isKanji(text)) { 22 | result = 'cjk'; 23 | } 24 | else { 25 | result = 'mix'; 26 | } 27 | return global.KIND[result]; 28 | }, 29 | isAscii: function(text) { 30 | var re = /^[\u0000-\u00ff]+$/; 31 | return re.test(text); 32 | }, 33 | isKanji: function(text) { 34 | var re = /^([\u4e00-\u9fcf]|[\u3400-\u4dbf]|[\u20000-\u2a6df]|[\uf900-\ufadf])+$/; 35 | return re.test(text); 36 | }, 37 | isHiragana: function(text) { 38 | var re = /^[\u3040-\u309f]+$/; 39 | return re.test(text) 40 | }, 41 | isKatakana: function(text) { 42 | var re = /^[\u30a0-\u30ff]+$/; 43 | return re.test(text); 44 | } 45 | }; 46 | return global; 47 | })(); 48 | -------------------------------------------------------------------------------- /samples/demos/assets/rangy-serializer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license Serializer module for Rangy. 3 | * Serializes Ranges and Selections. An example use would be to store a user's selection on a particular page in a 4 | * cookie or local storage and restore it on the user's next visit to the same page. 5 | * 6 | * Part of Rangy, a cross-browser JavaScript range and selection library 7 | * http://code.google.com/p/rangy/ 8 | * 9 | * Depends on Rangy core. 10 | * 11 | * Copyright 2012, Tim Down 12 | * Licensed under the MIT license. 13 | * Version: 1.2.3 14 | * Build date: 26 February 2012 15 | */ 16 | rangy.createModule("Serializer", function(api, module) { 17 | api.requireModules( ["WrappedSelection", "WrappedRange"] ); 18 | var UNDEF = "undefined"; 19 | 20 | // encodeURIComponent and decodeURIComponent are required for cookie handling 21 | if (typeof encodeURIComponent == UNDEF || typeof decodeURIComponent == UNDEF) { 22 | module.fail("Global object is missing encodeURIComponent and/or decodeURIComponent method"); 23 | } 24 | 25 | // Checksum for checking whether range can be serialized 26 | var crc32 = (function() { 27 | function utf8encode(str) { 28 | var utf8CharCodes = []; 29 | 30 | for (var i = 0, len = str.length, c; i < len; ++i) { 31 | c = str.charCodeAt(i); 32 | if (c < 128) { 33 | utf8CharCodes.push(c); 34 | } else if (c < 2048) { 35 | utf8CharCodes.push((c >> 6) | 192, (c & 63) | 128); 36 | } else { 37 | utf8CharCodes.push((c >> 12) | 224, ((c >> 6) & 63) | 128, (c & 63) | 128); 38 | } 39 | } 40 | return utf8CharCodes; 41 | } 42 | 43 | var cachedCrcTable = null; 44 | 45 | function buildCRCTable() { 46 | var table = []; 47 | for (var i = 0, j, crc; i < 256; ++i) { 48 | crc = i; 49 | j = 8; 50 | while (j--) { 51 | if ((crc & 1) == 1) { 52 | crc = (crc >>> 1) ^ 0xEDB88320; 53 | } else { 54 | crc >>>= 1; 55 | } 56 | } 57 | table[i] = crc >>> 0; 58 | } 59 | return table; 60 | } 61 | 62 | function getCrcTable() { 63 | if (!cachedCrcTable) { 64 | cachedCrcTable = buildCRCTable(); 65 | } 66 | return cachedCrcTable; 67 | } 68 | 69 | return function(str) { 70 | var utf8CharCodes = utf8encode(str), crc = -1, crcTable = getCrcTable(); 71 | for (var i = 0, len = utf8CharCodes.length, y; i < len; ++i) { 72 | y = (crc ^ utf8CharCodes[i]) & 0xFF; 73 | crc = (crc >>> 8) ^ crcTable[y]; 74 | } 75 | return (crc ^ -1) >>> 0; 76 | }; 77 | })(); 78 | 79 | var dom = api.dom; 80 | 81 | function escapeTextForHtml(str) { 82 | return str.replace(//g, ">"); 83 | } 84 | 85 | function nodeToInfoString(node, infoParts) { 86 | infoParts = infoParts || []; 87 | var nodeType = node.nodeType, children = node.childNodes, childCount = children.length; 88 | var nodeInfo = [nodeType, node.nodeName, childCount].join(":"); 89 | var start = "", end = ""; 90 | switch (nodeType) { 91 | case 3: // Text node 92 | start = escapeTextForHtml(node.nodeValue); 93 | break; 94 | case 8: // Comment 95 | start = ""; 96 | break; 97 | default: 98 | start = "<" + nodeInfo + ">"; 99 | end = ">"; 100 | break; 101 | } 102 | if (start) { 103 | infoParts.push(start); 104 | } 105 | for (var i = 0; i < childCount; ++i) { 106 | nodeToInfoString(children[i], infoParts); 107 | } 108 | if (end) { 109 | infoParts.push(end); 110 | } 111 | return infoParts; 112 | } 113 | 114 | // Creates a string representation of the specified element's contents that is similar to innerHTML but omits all 115 | // attributes and comments and includes child node counts. This is done instead of using innerHTML to work around 116 | // IE <= 8's policy of including element properties in attributes, which ruins things by changing an element's 117 | // innerHTML whenever the user changes an input within the element. 118 | function getElementChecksum(el) { 119 | var info = nodeToInfoString(el).join(""); 120 | return crc32(info).toString(16); 121 | } 122 | 123 | function serializePosition(node, offset, rootNode) { 124 | var pathBits = [], n = node; 125 | rootNode = rootNode || dom.getDocument(node).documentElement; 126 | while (n && n != rootNode) { 127 | pathBits.push(dom.getNodeIndex(n, true)); 128 | n = n.parentNode; 129 | } 130 | return pathBits.join("/") + ":" + offset; 131 | } 132 | 133 | function deserializePosition(serialized, rootNode, doc) { 134 | if (rootNode) { 135 | doc = doc || dom.getDocument(rootNode); 136 | } else { 137 | doc = doc || document; 138 | rootNode = doc.documentElement; 139 | } 140 | var bits = serialized.split(":"); 141 | var node = rootNode; 142 | var nodeIndices = bits[0] ? bits[0].split("/") : [], i = nodeIndices.length, nodeIndex; 143 | 144 | while (i--) { 145 | nodeIndex = parseInt(nodeIndices[i], 10); 146 | if (nodeIndex < node.childNodes.length) { 147 | node = node.childNodes[parseInt(nodeIndices[i], 10)]; 148 | } else { 149 | throw module.createError("deserializePosition failed: node " + dom.inspectNode(node) + 150 | " has no child with index " + nodeIndex + ", " + i); 151 | } 152 | } 153 | 154 | return new dom.DomPosition(node, parseInt(bits[1], 10)); 155 | } 156 | 157 | function serializeRange(range, omitChecksum, rootNode) { 158 | rootNode = rootNode || api.DomRange.getRangeDocument(range).documentElement; 159 | if (!dom.isAncestorOf(rootNode, range.commonAncestorContainer, true)) { 160 | throw new Error("serializeRange: range is not wholly contained within specified root node"); 161 | } 162 | var serialized = serializePosition(range.startContainer, range.startOffset, rootNode) + "," + 163 | serializePosition(range.endContainer, range.endOffset, rootNode); 164 | if (!omitChecksum) { 165 | serialized += "{" + getElementChecksum(rootNode) + "}"; 166 | } 167 | return serialized; 168 | } 169 | 170 | function deserializeRange(serialized, rootNode, doc) { 171 | if (rootNode) { 172 | doc = doc || dom.getDocument(rootNode); 173 | } else { 174 | doc = doc || document; 175 | rootNode = doc.documentElement; 176 | } 177 | var result = /^([^,]+),([^,\{]+)({([^}]+)})?$/.exec(serialized); 178 | var checksum = result[4], rootNodeChecksum = getElementChecksum(rootNode); 179 | if (checksum && checksum !== getElementChecksum(rootNode)) { 180 | throw new Error("deserializeRange: checksums of serialized range root node (" + checksum + 181 | ") and target root node (" + rootNodeChecksum + ") do not match"); 182 | } 183 | var start = deserializePosition(result[1], rootNode, doc), end = deserializePosition(result[2], rootNode, doc); 184 | var range = api.createRange(doc); 185 | range.setStart(start.node, start.offset); 186 | range.setEnd(end.node, end.offset); 187 | return range; 188 | } 189 | 190 | function canDeserializeRange(serialized, rootNode, doc) { 191 | if (rootNode) { 192 | doc = doc || dom.getDocument(rootNode); 193 | } else { 194 | doc = doc || document; 195 | rootNode = doc.documentElement; 196 | } 197 | var result = /^([^,]+),([^,]+)({([^}]+)})?$/.exec(serialized); 198 | var checksum = result[3]; 199 | return !checksum || checksum === getElementChecksum(rootNode); 200 | } 201 | 202 | function serializeSelection(selection, omitChecksum, rootNode) { 203 | selection = selection || api.getSelection(); 204 | var ranges = selection.getAllRanges(), serializedRanges = []; 205 | for (var i = 0, len = ranges.length; i < len; ++i) { 206 | serializedRanges[i] = serializeRange(ranges[i], omitChecksum, rootNode); 207 | } 208 | return serializedRanges.join("|"); 209 | } 210 | 211 | function deserializeSelection(serialized, rootNode, win) { 212 | if (rootNode) { 213 | win = win || dom.getWindow(rootNode); 214 | } else { 215 | win = win || window; 216 | rootNode = win.document.documentElement; 217 | } 218 | var serializedRanges = serialized.split("|"); 219 | var sel = api.getSelection(win); 220 | var ranges = []; 221 | 222 | for (var i = 0, len = serializedRanges.length; i < len; ++i) { 223 | ranges[i] = deserializeRange(serializedRanges[i], rootNode, win.document); 224 | } 225 | sel.setRanges(ranges); 226 | 227 | return sel; 228 | } 229 | 230 | function canDeserializeSelection(serialized, rootNode, win) { 231 | var doc; 232 | if (rootNode) { 233 | doc = win ? win.document : dom.getDocument(rootNode); 234 | } else { 235 | win = win || window; 236 | rootNode = win.document.documentElement; 237 | } 238 | var serializedRanges = serialized.split("|"); 239 | 240 | for (var i = 0, len = serializedRanges.length; i < len; ++i) { 241 | if (!canDeserializeRange(serializedRanges[i], rootNode, doc)) { 242 | return false; 243 | } 244 | } 245 | 246 | return true; 247 | } 248 | 249 | 250 | var cookieName = "rangySerializedSelection"; 251 | 252 | function getSerializedSelectionFromCookie(cookie) { 253 | var parts = cookie.split(/[;,]/); 254 | for (var i = 0, len = parts.length, nameVal, val; i < len; ++i) { 255 | nameVal = parts[i].split("="); 256 | if (nameVal[0].replace(/^\s+/, "") == cookieName) { 257 | val = nameVal[1]; 258 | if (val) { 259 | return decodeURIComponent(val.replace(/\s+$/, "")); 260 | } 261 | } 262 | } 263 | return null; 264 | } 265 | 266 | function restoreSelectionFromCookie(win) { 267 | win = win || window; 268 | var serialized = getSerializedSelectionFromCookie(win.document.cookie); 269 | if (serialized) { 270 | deserializeSelection(serialized, win.doc) 271 | } 272 | } 273 | 274 | function saveSelectionCookie(win, props) { 275 | win = win || window; 276 | props = (typeof props == "object") ? props : {}; 277 | var expires = props.expires ? ";expires=" + props.expires.toUTCString() : ""; 278 | var path = props.path ? ";path=" + props.path : ""; 279 | var domain = props.domain ? ";domain=" + props.domain : ""; 280 | var secure = props.secure ? ";secure" : ""; 281 | var serialized = serializeSelection(api.getSelection(win)); 282 | win.document.cookie = encodeURIComponent(cookieName) + "=" + encodeURIComponent(serialized) + expires + path + domain + secure; 283 | } 284 | 285 | api.serializePosition = serializePosition; 286 | api.deserializePosition = deserializePosition; 287 | 288 | api.serializeRange = serializeRange; 289 | api.deserializeRange = deserializeRange; 290 | api.canDeserializeRange = canDeserializeRange; 291 | 292 | api.serializeSelection = serializeSelection; 293 | api.deserializeSelection = deserializeSelection; 294 | api.canDeserializeSelection = canDeserializeSelection; 295 | 296 | api.restoreSelectionFromCookie = restoreSelectionFromCookie; 297 | api.saveSelectionCookie = saveSelectionCookie; 298 | 299 | api.getElementChecksum = getElementChecksum; 300 | }); 301 | -------------------------------------------------------------------------------- /samples/demos/proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | 22 | -optimizationpasses 2 23 | 24 | -keepattributes JavascriptInterface 25 | 26 | -keepclassmembers class com.bossturban.webviewmarker.TextSelectionController { 27 | public *; 28 | } 29 | 30 | -keepclassmembers class **.R$* { 31 | public static