diff options
-rw-r--r-- | include/touch/touch.h | 45 | ||||
-rw-r--r-- | ios/experimental/LibreOffice/LibreOffice/AppDelegate.m | 29 | ||||
-rw-r--r-- | ios/experimental/LibreOffice/LibreOffice/View.h | 3 | ||||
-rw-r--r-- | ios/experimental/LibreOffice/LibreOffice/View.m | 179 | ||||
-rw-r--r-- | sw/inc/viscrs.hxx | 4 | ||||
-rw-r--r-- | sw/source/core/crsr/viscrs.cxx | 45 |
6 files changed, 290 insertions, 15 deletions
diff --git a/include/touch/touch.h b/include/touch/touch.h index c8af48edabc8..11440f16062b 100644 --- a/include/touch/touch.h +++ b/include/touch/touch.h @@ -18,8 +18,24 @@ #if !HAVE_FEATURE_DESKTOP +// Let's try this way: Use Quartz 2D types for iOS, and LO's basegfx +// types for others, when/if this API is used for others. But of +// course, it is quite likely that some degree of redesign is needed +// at such a stage anyway... + +#ifdef IOS +#include <premac.h> +#include <CoreGraphics/CoreGraphics.h> +#include <postmac.h> +#else +#include <basegfx/range/b2ibox.hxx> +#endif + #ifdef __cplusplus extern "C" { +#if 0 +} // To avoid an editor indenting all inside the extern "C" +#endif #endif // These functions are the interface between the upper GUI layers of a @@ -41,6 +57,31 @@ void touch_ui_show_keyboard(); void touch_ui_hide_keyboard(); bool touch_ui_keyboard_visible(); +typedef enum { + MLOSelectionNone, + MLOSelectionText, + MLOSelectionGraphic +} MLOSelectionKind; + +#ifdef IOS +typedef CGRect MLORect; +#else +typedef basegfx::B2IBox MLORect; +#endif + +void touch_ui_selection_start(MLOSelectionKind kind, + const void *documentHandle, + MLORect *rectangles, + int rectangleCount, + void *preview); + +void touch_ui_selection_resize_done(bool success, + const void *documentHandle, + MLORect *rectangles, + int rectangleCount); + +void touch_ui_selection_none(); + // 2) Those implmented in the lower layers to be called by the upper // layer, in cases where we don't want to include a bunch of the // "normal" LibreOffice C++ headers in an otherwise purely Objective-C @@ -69,6 +110,10 @@ typedef enum { DOWN, MOVE, UP} MLOMouseButtonState; void touch_lo_mouse_drag(int x, int y, MLOMouseButtonState state); +void touch_lo_selection_attempt_resize(const void *documentHandle, + MLORect *selectedRectangles, + int numberOfRectangles); + #ifdef __cplusplus } #endif diff --git a/ios/experimental/LibreOffice/LibreOffice/AppDelegate.m b/ios/experimental/LibreOffice/LibreOffice/AppDelegate.m index c3ed9ebb7832..b4d027e44620 100644 --- a/ios/experimental/LibreOffice/LibreOffice/AppDelegate.m +++ b/ios/experimental/LibreOffice/LibreOffice/AppDelegate.m @@ -219,4 +219,33 @@ bool touch_ui_keyboard_visible() return keyboardShows; } +void touch_ui_selection_start(MLOSelectionKind kind, + const void *documentHandle, + MLORect *rectangles, + int rectangleCount, + void *preview) +{ + (void) preview; + + // Note that this is called on the LO thread + NSLog(@"==> touch_ui_selection_start"); + for(int i = 0; i < rectangleCount; ++i){ + NSLog(@" %fx%f@(%f,%f)", + rectangles[i].size.width, + rectangles[i].size.height, + rectangles[i].origin.x, + rectangles[i].origin.y); + } + dispatch_async(dispatch_get_main_queue(), ^{ + [theView startSelectionOfType:kind withNumber:rectangleCount ofRectangles:rectangles forDocument:documentHandle]; + }); +} + +void touch_ui_selection_none() +{ + dispatch_async(dispatch_get_main_queue(), ^{ + [theView startSelectionOfType:MLOSelectionNone withNumber:0 ofRectangles:NULL forDocument:NULL]; + }); +} + // vim:set shiftwidth=4 softtabstop=4 expandtab: diff --git a/ios/experimental/LibreOffice/LibreOffice/View.h b/ios/experimental/LibreOffice/LibreOffice/View.h index f036c488c338..aecc606425be 100644 --- a/ios/experimental/LibreOffice/LibreOffice/View.h +++ b/ios/experimental/LibreOffice/LibreOffice/View.h @@ -9,6 +9,8 @@ #import <UIKit/UIKit.h> +#import <touch/touch.h> + @interface View : UIView { @public @@ -18,6 +20,7 @@ - (void)tapGesture:(UITapGestureRecognizer *)gestureRecognizer; - (void)panGesture:(UIPanGestureRecognizer *)gestureRecognizer; - (void)longPressGesture:(UILongPressGestureRecognizer *)gestureRecognizer; +- (void)startSelectionOfType:(MLOSelectionKind)kind withNumber:(int)number ofRectangles:(CGRect *)rects forDocument:(const void *)document; @end diff --git a/ios/experimental/LibreOffice/LibreOffice/View.m b/ios/experimental/LibreOffice/LibreOffice/View.m index de7b31144ac3..2e5f3ef26e73 100644 --- a/ios/experimental/LibreOffice/LibreOffice/View.m +++ b/ios/experimental/LibreOffice/LibreOffice/View.m @@ -10,15 +10,112 @@ #include <touch/touch.h> +@interface View () +@property const void *documentHandle; +@property CGRect *selectionRectangles; +@property int selectionRectangleCount; +@end + +#define HANDLE_BLOB 20 +#define HANDLE_STEM_WIDTH 6 +#define HANDLE_STEM_HEIGHT 20 + @implementation View +#if 0 +- (id) initWithFrame:(CGRect)rect +{ + self = [super initWithFrame:rect]; + if (self) { + self.selectionRectangles = NULL; + self.selectionRectangleCount = 0; + } + return self; +} +#endif + +- (CGRect) topLeftResizeHandle +{ + if (self.selectionRectangleCount == 0) + return CGRectNull; + + return CGRectMake(self.selectionRectangles[0].origin.x - HANDLE_STEM_WIDTH/2 - HANDLE_BLOB/2, + self.selectionRectangles[0].origin.y - HANDLE_STEM_HEIGHT - HANDLE_BLOB, + HANDLE_BLOB, HANDLE_BLOB); +} + +- (CGRect) bottomRightResizeHandle +{ + const int N = self.selectionRectangleCount; + + if (N == 0) + return CGRectNull; + + return CGRectMake(self.selectionRectangles[N-1].origin.x + + self.selectionRectangles[N-1].size.width + HANDLE_STEM_WIDTH/2 - HANDLE_BLOB/2, + self.selectionRectangles[N-1].origin.y + + self.selectionRectangles[N-1].size.height + HANDLE_STEM_HEIGHT, + HANDLE_BLOB, HANDLE_BLOB); +} + +- (void) requestSelectionRedisplay +{ + if (self.selectionRectangleCount == 0) + return; + + CGRect r = CGRectNull; + for (int i = 0; i < self.selectionRectangleCount; i++) { + r = CGRectUnion(r, self.selectionRectangles[i]); + } + r = CGRectUnion(r, [self topLeftResizeHandle]); + r = CGRectUnion(r, [self bottomRightResizeHandle]); + + [self setNeedsDisplayInRect:r]; +} + +- (void) drawSelectionIntoContext:(CGContextRef)context +{ + if (self.selectionRectangleCount == 0) + return; + + const int N = self.selectionRectangleCount; + + CGContextSetFillColorWithColor(context, [[UIColor colorWithRed:0 green:0 blue:1 alpha:0.5] CGColor]); + +#if 0 + for (int i = 0; i < N; i++) { + NSLog(@"UIRectFill: %fx%f@(%f,%f)", + self.selectionRectangles[i].size.width, self.selectionRectangles[i].size.height, + self.selectionRectangles[i].origin.x, self.selectionRectangles[i].origin.y); + UIRectFillUsingBlendMode(CGRectMake(self.selectionRectangles[i].origin.x, self.selectionRectangles[i].origin.y, + self.selectionRectangles[i].size.width, self.selectionRectangles[i].size.height), + kCGBlendModeNormal); + } +#else + CGContextSetBlendMode(context, kCGBlendModeNormal); + CGContextFillRects(context, self.selectionRectangles, self.selectionRectangleCount); +#endif + + CGContextFillRect(context, + CGRectMake(self.selectionRectangles[0].origin.x - HANDLE_STEM_WIDTH, + self.selectionRectangles[0].origin.y - HANDLE_STEM_HEIGHT, + HANDLE_STEM_WIDTH, self.selectionRectangles[0].size.height + HANDLE_STEM_HEIGHT)); + + CGContextFillRect(context, + CGRectMake(self.selectionRectangles[N-1].origin.x + + self.selectionRectangles[N-1].size.width, + self.selectionRectangles[N-1].origin.y, + HANDLE_STEM_WIDTH, self.selectionRectangles[N-1].size.height + HANDLE_STEM_HEIGHT)); + + CGContextFillEllipseInRect(context, [self topLeftResizeHandle]); + CGContextFillEllipseInRect(context, [self bottomRightResizeHandle]); +} + - (void)drawRect:(CGRect)rect { - // NSLog(@"drawRect: %dx%d@(%d,%d)", (int) rect.size.width, (int) rect.size.height, (int) rect.origin.x, (int) rect.origin.y); + NSLog(@"View drawRect: %dx%d@(%d,%d)", (int) rect.size.width, (int) rect.size.height, (int) rect.origin.x, (int) rect.origin.y); // NSLog(@"statusBarOrientation: %ld", (long)[[UIApplication sharedApplication] statusBarOrientation]); - // NSDate *startDate = [NSDate date]; - CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSaveGState(context); @@ -41,15 +138,23 @@ break; } touch_lo_render_windows(context, rect.origin.y, rect.origin.y, rect.size.width, rect.size.height); + CGContextRestoreGState(context); - // NSLog(@"drawRect: touch_lo_render_windows took %f s", [[NSDate date] timeIntervalSinceDate: startDate]); + [self drawSelectionIntoContext:context]; } +#if 0 +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event +{ + NSLog(@"===> View touchesBegan!"); +} +#endif + - (void)tapGesture:(UITapGestureRecognizer *)gestureRecognizer { if ([gestureRecognizer state] == UIGestureRecognizerStateEnded) { - CGPoint location = [gestureRecognizer locationInView: self]; + CGPoint location = [gestureRecognizer locationInView:self]; // NSLog(@"tapGesture: at: (%d,%d)", (int)location.x, (int)location.y); @@ -63,7 +168,37 @@ { static CGFloat previousX = 0.0f, previousY = 0.0f; - CGPoint translation = [gestureRecognizer translationInView: self]; + CGPoint translation = [gestureRecognizer translationInView:self]; + + if ([gestureRecognizer numberOfTouches] == 1) { + if (CGRectContainsPoint([self topLeftResizeHandle], + [gestureRecognizer locationInView:self])) { + + self.selectionRectangles[0].origin.x += translation.x; + self.selectionRectangles[0].origin.y += translation.y; + self.selectionRectangles[0].size.width -= translation.x; + self.selectionRectangles[0].size.height -= translation.y; + + touch_lo_selection_attempt_resize(self.documentHandle, + self.selectionRectangles, + self.selectionRectangleCount); + return; + } else if (CGRectContainsPoint([self bottomRightResizeHandle], + [gestureRecognizer locationInView:self])) { + + const int N = self.selectionRectangleCount - 1; + + self.selectionRectangles[N].origin.x += translation.x; + self.selectionRectangles[N].origin.y += translation.y; + self.selectionRectangles[N].size.width -= translation.x; + self.selectionRectangles[N].size.height -= translation.y; + + touch_lo_selection_attempt_resize(self.documentHandle, + self.selectionRectangles, + self.selectionRectangleCount); + return; + } + } if (gestureRecognizer.state != UIGestureRecognizerStateBegan) { int deltaX = translation.x - previousX; @@ -80,7 +215,7 @@ - (void)pinchGesture:(UIPinchGestureRecognizer *)gestureRecognizer { - CGPoint location = [gestureRecognizer locationInView: self]; + CGPoint location = [gestureRecognizer locationInView:self]; CGFloat scale = gestureRecognizer.scale; // NSLog(@"pinchGesture: pinch: (%f) cords (%d,%d)", (float)scale, (int)location.x, (int)location.y ); @@ -88,7 +223,7 @@ touch_lo_zoom((int)location.x, (int)location.y, (float)scale); // to reset the gesture scaling - if (gestureRecognizer.state==UIGestureRecognizerStateEnded) { + if (gestureRecognizer.state == UIGestureRecognizerStateEnded) { touch_lo_zoom(1, 1, 0.0f); } } @@ -97,16 +232,34 @@ { CGPoint point = [gestureRecognizer locationInView:self]; - UIGestureRecognizerState state = gestureRecognizer.state; - - // NSLog(@"longPressGesture: state %d cords (%d,%d)",state ,(int)point.x,(int)point.y); - - if (state == UIGestureRecognizerStateEnded) { + if (gestureRecognizer.state == UIGestureRecognizerStateEnded) { touch_lo_tap(point.x, point.y); touch_lo_tap(point.x, point.y); } } +- (void)startSelectionOfType:(MLOSelectionKind)kind withNumber:(int)number ofRectangles:(CGRect *)rects forDocument:(const void *)document +{ + (void) kind; + + // First request the old selection area to be redisplayed + [self requestSelectionRedisplay]; + + free(self.selectionRectangles); + self.selectionRectangles = NULL; + self.selectionRectangleCount = 0; + self.documentHandle = NULL; + + if (number == 0) + return; + + self.selectionRectangles = rects; + self.selectionRectangleCount = number; + self.documentHandle = document; + + [self requestSelectionRedisplay]; +} + @end // vim:set shiftwidth=4 softtabstop=4 expandtab: diff --git a/sw/inc/viscrs.hxx b/sw/inc/viscrs.hxx index a38fc3e257bc..aef159dc2f3e 100644 --- a/sw/inc/viscrs.hxx +++ b/sw/inc/viscrs.hxx @@ -19,6 +19,8 @@ #ifndef _VISCRS_HXX #define _VISCRS_HXX +#include <config_features.h> + #include <vcl/cursor.hxx> #include "swcrsr.hxx" #include "swrect.hxx" @@ -71,11 +73,13 @@ class SwSelPaintRects : public SwRects virtual void Paint( const Rectangle& rRect ); virtual void FillRects() = 0; +#if HAVE_FEATURE_DESKTOP sdr::overlay::OverlayObject* mpCursorOverlay; // access to mpCursorOverlay for swapContent sdr::overlay::OverlayObject* getCursorOverlay() const { return mpCursorOverlay; } void setCursorOverlay(sdr::overlay::OverlayObject* pNew) { mpCursorOverlay = pNew; } +#endif public: SwSelPaintRects( const SwCrsrShell& rCSh ); diff --git a/sw/source/core/crsr/viscrs.cxx b/sw/source/core/crsr/viscrs.cxx index 8f73dc9cd68d..a369f65778b2 100644 --- a/sw/source/core/crsr/viscrs.cxx +++ b/sw/source/core/crsr/viscrs.cxx @@ -17,6 +17,8 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <config_features.h> + #include <vcl/dialog.hxx> #include <vcl/msgbox.hxx> #include <vcl/wrkwin.hxx> @@ -42,6 +44,8 @@ #include <vcl/svapp.hxx> #include <svx/sdr/overlay/overlayselection.hxx> +#include <touch/touch.h> + extern void SwCalcPixStatics( OutputDevice *pOut ); // Here static members are defined. They will get changed on alteration of the @@ -184,8 +188,10 @@ void SwVisCrsr::_SetPosAndShow() SwSelPaintRects::SwSelPaintRects( const SwCrsrShell& rCSh ) : SwRects(), - pCShell( &rCSh ), - mpCursorOverlay(0) + pCShell( &rCSh ) +#if HAVE_FEATURE_DESKTOP + , mpCursorOverlay(0) +#endif { } @@ -198,19 +204,23 @@ void SwSelPaintRects::swapContent(SwSelPaintRects& rSwap) { SwRects::swap(rSwap); +#if HAVE_FEATURE_DESKTOP // #i75172# also swap mpCursorOverlay sdr::overlay::OverlayObject* pTempOverlay = getCursorOverlay(); setCursorOverlay(rSwap.getCursorOverlay()); rSwap.setCursorOverlay(pTempOverlay); +#endif } void SwSelPaintRects::Hide() { +#if HAVE_FEATURE_DESKTOP if(mpCursorOverlay) { delete mpCursorOverlay; mpCursorOverlay = 0; } +#endif SwRects::clear(); } @@ -225,6 +235,7 @@ void SwSelPaintRects::Show() SwRects::clear(); FillRects(); +#if HAVE_FEATURE_DESKTOP // get new rects std::vector< basegfx::B2DRange > aNewRanges; @@ -250,8 +261,27 @@ void SwSelPaintRects::Show() mpCursorOverlay = 0; } } +#else + if (false) + ; +#endif else if(!empty()) { +#if !HAVE_FEATURE_DESKTOP && defined IOS + const OutputDevice* pOut = GetShell()->GetWin(); + if ( ! pOut ) + pOut = GetShell()->GetOut(); + // Buffer will be deallocated in the UI layer + CGRect *rects = (CGRect *) malloc((sizeof(CGRect))*size()); + for (size_t i = 0; i < size(); ++i) + { + Point origin = pOut->LogicToPixel((*this)[i].Pos()); + Size size = pOut->LogicToPixel((*this)[i].SSize()); + rects[i] = CGRectMake(origin.X(), origin.Y(), + size.Width(), size.Height()); + } + touch_ui_selection_start(MLOSelectionText, GetShell(), rects, size(), NULL); +#else SdrPaintWindow* pCandidate = pView->GetPaintWindow(0); rtl::Reference< ::sdr::overlay::OverlayManager > xTargetOverlay = pCandidate->GetOverlayManager(); @@ -270,10 +300,21 @@ void SwSelPaintRects::Show() xTargetOverlay->add(*mpCursorOverlay); } +#endif } } } +#if !HAVE_FEATURE_DESKTOP + +extern "C" void touch_lo_selection_attempt_resize(const void * /* documentHandle */, + MLORect * /* selectedRectangles */, + int /* numberOfRectangles */) +{ +} + +#endif + void SwSelPaintRects::Invalidate( const SwRect& rRect ) { sal_uInt16 nSz = size(); |