summaryrefslogtreecommitdiff
path: root/ios/shared
diff options
context:
space:
mode:
authorptyl@cloudon.com <ptyl@cloudon.com>2013-10-15 22:28:11 +0200
committerTor Lillqvist <tml@collabora.com>2013-10-15 22:52:06 +0300
commit2b60f46e25adfce0f87424513e492c446f8df528 (patch)
tree2622a16f0911e2b25c1f990099c9b358f31a2574 /ios/shared
parent79d83741eb0d60d741415de8b8f01b3ef8510ae2 (diff)
Add the new iOS app project files
Change-Id: I9ac049ef61e698afda1577a630e1185c75a33734
Diffstat (limited to 'ios/shared')
-rw-r--r--ios/shared/ios_sharedlo.xcodeproj/project.pbxproj589
-rw-r--r--ios/shared/ios_sharedlo/cxx/mlo.h19
-rw-r--r--ios/shared/ios_sharedlo/cxx/mlo.mm219
-rw-r--r--ios/shared/ios_sharedlo/cxx/mlo_uno.h30
-rw-r--r--ios/shared/ios_sharedlo/cxx/mlo_uno.mm480
-rw-r--r--ios/shared/ios_sharedlo/cxx/mlo_utils.h22
-rw-r--r--ios/shared/ios_sharedlo/cxx/mlo_utils.mm16
-rw-r--r--ios/shared/ios_sharedlo/cxx/time.h159
-rw-r--r--ios/shared/ios_sharedlo/ios_sharedlo-Prefix.pch8
-rw-r--r--ios/shared/ios_sharedlo/ios_sharedlo.h13
-rw-r--r--ios/shared/ios_sharedlo/ios_sharedlo.m13
-rw-r--r--ios/shared/ios_sharedlo/objective_c/MLOInvoker.h21
-rw-r--r--ios/shared/ios_sharedlo/objective_c/MLOManager.h27
-rw-r--r--ios/shared/ios_sharedlo/objective_c/MLOManager.m215
-rw-r--r--ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureEngine.h19
-rw-r--r--ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureEngine.m458
-rw-r--r--ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureEngine_Impl.h35
-rw-r--r--ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureFlick.h16
-rw-r--r--ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureFlick.m224
-rw-r--r--ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureLimiter.h33
-rw-r--r--ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureLimiter.m269
-rw-r--r--ios/shared/ios_sharedlo/objective_c/gestures/MLOKeyboardManager.h18
-rw-r--r--ios/shared/ios_sharedlo/objective_c/gestures/MLOKeyboardManager.m111
-rw-r--r--ios/shared/ios_sharedlo/objective_c/render/MLOPostRenderManager.h13
-rw-r--r--ios/shared/ios_sharedlo/objective_c/render/MLOPostRenderManager.m34
-rw-r--r--ios/shared/ios_sharedlo/objective_c/render/MLORenderBuffer.h19
-rw-r--r--ios/shared/ios_sharedlo/objective_c/render/MLORenderBuffer.m106
-rw-r--r--ios/shared/ios_sharedlo/objective_c/render/MLORenderManager.h30
-rw-r--r--ios/shared/ios_sharedlo/objective_c/render/MLORenderManager.m332
-rw-r--r--ios/shared/ios_sharedlo/objective_c/render/MLORenderManager_Impl.h26
-rw-r--r--ios/shared/ios_sharedlo/objective_c/render/MLORenderingUIView.h16
-rw-r--r--ios/shared/ios_sharedlo/objective_c/render/MLORenderingUIView.m20
-rw-r--r--ios/shared/ios_sharedlo/objective_c/render/MLOScalingBuffer.h16
-rw-r--r--ios/shared/ios_sharedlo/objective_c/render/MLOScalingBuffer.m79
-rw-r--r--ios/shared/ios_sharedlo/objective_c/utils/MLOAnimation.h36
-rw-r--r--ios/shared/ios_sharedlo/objective_c/utils/MLOAnimation.m149
-rw-r--r--ios/shared/ios_sharedlo/objective_c/utils/MLOButton.h19
-rw-r--r--ios/shared/ios_sharedlo/objective_c/utils/MLOButton.m35
-rw-r--r--ios/shared/ios_sharedlo/objective_c/utils/MLOCommon.h59
-rw-r--r--ios/shared/ios_sharedlo/objective_c/utils/MLOObject.h14
-rw-r--r--ios/shared/ios_sharedlo/objective_c/utils/MLOObject.m13
-rw-r--r--ios/shared/ios_sharedlo/objective_c/utils/MLOResourceImage.h32
-rw-r--r--ios/shared/ios_sharedlo/objective_c/utils/MLOResourceImage.m104
-rw-r--r--ios/shared/ios_sharedlo/objective_c/utils/MLOSubView.h26
-rw-r--r--ios/shared/ios_sharedlo/objective_c/utils/MLOSubView.m97
-rw-r--r--ios/shared/ios_sharedlo/objective_c/utils/MLOViewController.h14
-rw-r--r--ios/shared/ios_sharedlo/objective_c/utils/MLOViewController.m18
-rw-r--r--ios/shared/ios_sharedlo/objective_c/utils/NSObject+MLOUtils.h16
-rw-r--r--ios/shared/ios_sharedlo/objective_c/utils/NSObject+MLOUtils.m66
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/MLOMainViewController.h28
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/MLOMainViewController.m256
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/MLOMainViewController_Impl.h18
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/MLOTopbarViewController.h17
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/MLOTopbarViewController.m93
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerData.h33
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerData.m209
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerGridViewController.h19
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerGridViewController.m136
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerTooltip.h16
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerTooltip.m78
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerViewController.h26
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerViewController.m157
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOContextualMenuFocus.h17
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOContextualMenuFocus.m61
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOMagnifier.h20
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOMagnifier.m94
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOSelectionHandle.h22
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOSelectionHandle.m168
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOSelectionViewController.h22
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOSelectionViewController.m231
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOSelectionViewController_Impl.h17
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOThesaurusViewController.h15
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOThesaurusViewController.m48
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOFinder.h18
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOFinder.m281
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOToolbarButton.h31
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOToolbarButton.m157
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOToolbarViewController.h21
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOToolbarViewController.m136
-rw-r--r--ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOToolbarViewController_Impl.h13
80 files changed, 6861 insertions, 0 deletions
diff --git a/ios/shared/ios_sharedlo.xcodeproj/project.pbxproj b/ios/shared/ios_sharedlo.xcodeproj/project.pbxproj
new file mode 100644
index 000000000000..97714fae8ccd
--- /dev/null
+++ b/ios/shared/ios_sharedlo.xcodeproj/project.pbxproj
@@ -0,0 +1,589 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 681D78C7180C298700D52D5E /* MLOInvoker.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 689EBB441806D22C002F1CD7 /* MLOInvoker.h */; };
+ 681D78C8180C298700D52D5E /* MLOManager.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 689EBB451806D22C002F1CD7 /* MLOManager.h */; };
+ 681D78CD180C30B300D52D5E /* MLOObject.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 689EBB591806D22C002F1CD7 /* MLOObject.h */; };
+ 689EBB381806D221002F1CD7 /* mlo.mm in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB321806D221002F1CD7 /* mlo.mm */; };
+ 689EBB391806D221002F1CD7 /* mlo_uno.mm in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB341806D221002F1CD7 /* mlo_uno.mm */; };
+ 689EBB3A1806D221002F1CD7 /* mlo_utils.mm in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB361806D221002F1CD7 /* mlo_utils.mm */; };
+ 689EBB861806D22D002F1CD7 /* MLOGestureEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB3E1806D22C002F1CD7 /* MLOGestureEngine.m */; };
+ 689EBB871806D22D002F1CD7 /* MLOGestureFlick.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB411806D22C002F1CD7 /* MLOGestureFlick.m */; };
+ 689EBB881806D22D002F1CD7 /* MLOGestureLimiter.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB431806D22C002F1CD7 /* MLOGestureLimiter.m */; };
+ 689EBB891806D22D002F1CD7 /* MLOManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB461806D22C002F1CD7 /* MLOManager.m */; };
+ 689EBB8A1806D22D002F1CD7 /* MLOPostRenderManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB491806D22C002F1CD7 /* MLOPostRenderManager.m */; };
+ 689EBB8B1806D22D002F1CD7 /* MLORenderBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB4B1806D22C002F1CD7 /* MLORenderBuffer.m */; };
+ 689EBB8C1806D22D002F1CD7 /* MLORenderingUIView.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB4D1806D22C002F1CD7 /* MLORenderingUIView.m */; };
+ 689EBB8D1806D22D002F1CD7 /* MLORenderManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB4F1806D22C002F1CD7 /* MLORenderManager.m */; };
+ 689EBB8E1806D22D002F1CD7 /* MLOScalingBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB521806D22C002F1CD7 /* MLOScalingBuffer.m */; };
+ 689EBB8F1806D22D002F1CD7 /* MLOAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB551806D22C002F1CD7 /* MLOAnimation.m */; };
+ 689EBB901806D22D002F1CD7 /* MLOButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB571806D22C002F1CD7 /* MLOButton.m */; };
+ 689EBB911806D22D002F1CD7 /* MLOObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB5A1806D22C002F1CD7 /* MLOObject.m */; };
+ 689EBB921806D22D002F1CD7 /* MLOResourceImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB5C1806D22C002F1CD7 /* MLOResourceImage.m */; };
+ 689EBB931806D22D002F1CD7 /* MLOSubView.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB5E1806D22C002F1CD7 /* MLOSubView.m */; };
+ 689EBB941806D22D002F1CD7 /* MLOViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB601806D22C002F1CD7 /* MLOViewController.m */; };
+ 689EBB951806D22D002F1CD7 /* NSObject+MLOUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB621806D22C002F1CD7 /* NSObject+MLOUtils.m */; };
+ 689EBB961806D22D002F1CD7 /* MLOMainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB651806D22C002F1CD7 /* MLOMainViewController.m */; };
+ 689EBB971806D22D002F1CD7 /* MLOTopbarViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB691806D22C002F1CD7 /* MLOTopbarViewController.m */; };
+ 689EBB981806D22D002F1CD7 /* MLOScrollerData.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB6C1806D22C002F1CD7 /* MLOScrollerData.m */; };
+ 689EBB991806D22D002F1CD7 /* MLOScrollerGridViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB6E1806D22C002F1CD7 /* MLOScrollerGridViewController.m */; };
+ 689EBB9A1806D22D002F1CD7 /* MLOScrollerTooltip.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB701806D22C002F1CD7 /* MLOScrollerTooltip.m */; };
+ 689EBB9B1806D22D002F1CD7 /* MLOScrollerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB721806D22C002F1CD7 /* MLOScrollerViewController.m */; };
+ 689EBB9C1806D22D002F1CD7 /* MLOContextualMenuFocus.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB751806D22C002F1CD7 /* MLOContextualMenuFocus.m */; };
+ 689EBB9D1806D22D002F1CD7 /* MLOMagnifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB771806D22C002F1CD7 /* MLOMagnifier.m */; };
+ 689EBB9E1806D22D002F1CD7 /* MLOSelectionHandle.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB791806D22C002F1CD7 /* MLOSelectionHandle.m */; };
+ 689EBB9F1806D22D002F1CD7 /* MLOSelectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB7B1806D22C002F1CD7 /* MLOSelectionViewController.m */; };
+ 689EBBA01806D22D002F1CD7 /* MLOThesaurusViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB7E1806D22C002F1CD7 /* MLOThesaurusViewController.m */; };
+ 689EBBA11806D22D002F1CD7 /* MLOFinder.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB811806D22C002F1CD7 /* MLOFinder.m */; };
+ 689EBBA21806D22D002F1CD7 /* MLOToolbarButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB831806D22C002F1CD7 /* MLOToolbarButton.m */; };
+ 689EBBA31806D22D002F1CD7 /* MLOToolbarViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 689EBB851806D22D002F1CD7 /* MLOToolbarViewController.m */; };
+ 68FDBE2E18053A140064DD74 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 68FDBE2D18053A140064DD74 /* Foundation.framework */; };
+ 68FDBE3518053A140064DD74 /* ios_sharedlo.m in Sources */ = {isa = PBXBuildFile; fileRef = 68FDBE3418053A140064DD74 /* ios_sharedlo.m */; };
+ 88A2ED23180D4D7C009F39C0 /* MLOKeyboardManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 88A2ED22180D4D7C009F39C0 /* MLOKeyboardManager.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 68FDBE2818053A140064DD74 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "include/${PRODUCT_NAME}";
+ dstSubfolderSpec = 16;
+ files = (
+ 681D78CD180C30B300D52D5E /* MLOObject.h in CopyFiles */,
+ 681D78C7180C298700D52D5E /* MLOInvoker.h in CopyFiles */,
+ 681D78C8180C298700D52D5E /* MLOManager.h in CopyFiles */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 689EBADD1806975D002F1CD7 /* lo.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = lo.xcconfig; path = ../lo.xcconfig; sourceTree = "<group>"; };
+ 689EBB311806D221002F1CD7 /* mlo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mlo.h; sourceTree = "<group>"; };
+ 689EBB321806D221002F1CD7 /* mlo.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = mlo.mm; sourceTree = "<group>"; };
+ 689EBB331806D221002F1CD7 /* mlo_uno.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mlo_uno.h; sourceTree = "<group>"; };
+ 689EBB341806D221002F1CD7 /* mlo_uno.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = mlo_uno.mm; sourceTree = "<group>"; };
+ 689EBB351806D221002F1CD7 /* mlo_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mlo_utils.h; sourceTree = "<group>"; };
+ 689EBB361806D221002F1CD7 /* mlo_utils.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = mlo_utils.mm; sourceTree = "<group>"; };
+ 689EBB371806D221002F1CD7 /* time.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = time.h; sourceTree = "<group>"; };
+ 689EBB3D1806D22C002F1CD7 /* MLOGestureEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOGestureEngine.h; sourceTree = "<group>"; };
+ 689EBB3E1806D22C002F1CD7 /* MLOGestureEngine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLOGestureEngine.m; sourceTree = "<group>"; };
+ 689EBB3F1806D22C002F1CD7 /* MLOGestureEngine_Impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOGestureEngine_Impl.h; sourceTree = "<group>"; };
+ 689EBB401806D22C002F1CD7 /* MLOGestureFlick.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOGestureFlick.h; sourceTree = "<group>"; };
+ 689EBB411806D22C002F1CD7 /* MLOGestureFlick.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLOGestureFlick.m; sourceTree = "<group>"; };
+ 689EBB421806D22C002F1CD7 /* MLOGestureLimiter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOGestureLimiter.h; sourceTree = "<group>"; };
+ 689EBB431806D22C002F1CD7 /* MLOGestureLimiter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLOGestureLimiter.m; sourceTree = "<group>"; };
+ 689EBB441806D22C002F1CD7 /* MLOInvoker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOInvoker.h; sourceTree = "<group>"; };
+ 689EBB451806D22C002F1CD7 /* MLOManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOManager.h; sourceTree = "<group>"; };
+ 689EBB461806D22C002F1CD7 /* MLOManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLOManager.m; sourceTree = "<group>"; };
+ 689EBB481806D22C002F1CD7 /* MLOPostRenderManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOPostRenderManager.h; sourceTree = "<group>"; };
+ 689EBB491806D22C002F1CD7 /* MLOPostRenderManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLOPostRenderManager.m; sourceTree = "<group>"; };
+ 689EBB4A1806D22C002F1CD7 /* MLORenderBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLORenderBuffer.h; sourceTree = "<group>"; };
+ 689EBB4B1806D22C002F1CD7 /* MLORenderBuffer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLORenderBuffer.m; sourceTree = "<group>"; };
+ 689EBB4C1806D22C002F1CD7 /* MLORenderingUIView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLORenderingUIView.h; sourceTree = "<group>"; };
+ 689EBB4D1806D22C002F1CD7 /* MLORenderingUIView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLORenderingUIView.m; sourceTree = "<group>"; };
+ 689EBB4E1806D22C002F1CD7 /* MLORenderManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLORenderManager.h; sourceTree = "<group>"; };
+ 689EBB4F1806D22C002F1CD7 /* MLORenderManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLORenderManager.m; sourceTree = "<group>"; };
+ 689EBB501806D22C002F1CD7 /* MLORenderManager_Impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLORenderManager_Impl.h; sourceTree = "<group>"; };
+ 689EBB511806D22C002F1CD7 /* MLOScalingBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOScalingBuffer.h; sourceTree = "<group>"; };
+ 689EBB521806D22C002F1CD7 /* MLOScalingBuffer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLOScalingBuffer.m; sourceTree = "<group>"; };
+ 689EBB541806D22C002F1CD7 /* MLOAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOAnimation.h; sourceTree = "<group>"; };
+ 689EBB551806D22C002F1CD7 /* MLOAnimation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLOAnimation.m; sourceTree = "<group>"; };
+ 689EBB561806D22C002F1CD7 /* MLOButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOButton.h; sourceTree = "<group>"; };
+ 689EBB571806D22C002F1CD7 /* MLOButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLOButton.m; sourceTree = "<group>"; };
+ 689EBB581806D22C002F1CD7 /* MLOCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOCommon.h; sourceTree = "<group>"; };
+ 689EBB591806D22C002F1CD7 /* MLOObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOObject.h; sourceTree = "<group>"; };
+ 689EBB5A1806D22C002F1CD7 /* MLOObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLOObject.m; sourceTree = "<group>"; };
+ 689EBB5B1806D22C002F1CD7 /* MLOResourceImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOResourceImage.h; sourceTree = "<group>"; };
+ 689EBB5C1806D22C002F1CD7 /* MLOResourceImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLOResourceImage.m; sourceTree = "<group>"; };
+ 689EBB5D1806D22C002F1CD7 /* MLOSubView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOSubView.h; sourceTree = "<group>"; };
+ 689EBB5E1806D22C002F1CD7 /* MLOSubView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLOSubView.m; sourceTree = "<group>"; };
+ 689EBB5F1806D22C002F1CD7 /* MLOViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOViewController.h; sourceTree = "<group>"; };
+ 689EBB601806D22C002F1CD7 /* MLOViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLOViewController.m; sourceTree = "<group>"; };
+ 689EBB611806D22C002F1CD7 /* NSObject+MLOUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+MLOUtils.h"; sourceTree = "<group>"; };
+ 689EBB621806D22C002F1CD7 /* NSObject+MLOUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+MLOUtils.m"; sourceTree = "<group>"; };
+ 689EBB641806D22C002F1CD7 /* MLOMainViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOMainViewController.h; sourceTree = "<group>"; };
+ 689EBB651806D22C002F1CD7 /* MLOMainViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLOMainViewController.m; sourceTree = "<group>"; };
+ 689EBB661806D22C002F1CD7 /* MLOMainViewController_Impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOMainViewController_Impl.h; sourceTree = "<group>"; };
+ 689EBB681806D22C002F1CD7 /* MLOTopbarViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOTopbarViewController.h; sourceTree = "<group>"; };
+ 689EBB691806D22C002F1CD7 /* MLOTopbarViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLOTopbarViewController.m; sourceTree = "<group>"; };
+ 689EBB6B1806D22C002F1CD7 /* MLOScrollerData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOScrollerData.h; sourceTree = "<group>"; };
+ 689EBB6C1806D22C002F1CD7 /* MLOScrollerData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLOScrollerData.m; sourceTree = "<group>"; };
+ 689EBB6D1806D22C002F1CD7 /* MLOScrollerGridViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOScrollerGridViewController.h; sourceTree = "<group>"; };
+ 689EBB6E1806D22C002F1CD7 /* MLOScrollerGridViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLOScrollerGridViewController.m; sourceTree = "<group>"; };
+ 689EBB6F1806D22C002F1CD7 /* MLOScrollerTooltip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOScrollerTooltip.h; sourceTree = "<group>"; };
+ 689EBB701806D22C002F1CD7 /* MLOScrollerTooltip.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLOScrollerTooltip.m; sourceTree = "<group>"; };
+ 689EBB711806D22C002F1CD7 /* MLOScrollerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOScrollerViewController.h; sourceTree = "<group>"; };
+ 689EBB721806D22C002F1CD7 /* MLOScrollerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLOScrollerViewController.m; sourceTree = "<group>"; };
+ 689EBB741806D22C002F1CD7 /* MLOContextualMenuFocus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOContextualMenuFocus.h; sourceTree = "<group>"; };
+ 689EBB751806D22C002F1CD7 /* MLOContextualMenuFocus.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLOContextualMenuFocus.m; sourceTree = "<group>"; };
+ 689EBB761806D22C002F1CD7 /* MLOMagnifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOMagnifier.h; sourceTree = "<group>"; };
+ 689EBB771806D22C002F1CD7 /* MLOMagnifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLOMagnifier.m; sourceTree = "<group>"; };
+ 689EBB781806D22C002F1CD7 /* MLOSelectionHandle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOSelectionHandle.h; sourceTree = "<group>"; };
+ 689EBB791806D22C002F1CD7 /* MLOSelectionHandle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLOSelectionHandle.m; sourceTree = "<group>"; };
+ 689EBB7A1806D22C002F1CD7 /* MLOSelectionViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOSelectionViewController.h; sourceTree = "<group>"; };
+ 689EBB7B1806D22C002F1CD7 /* MLOSelectionViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLOSelectionViewController.m; sourceTree = "<group>"; };
+ 689EBB7C1806D22C002F1CD7 /* MLOSelectionViewController_Impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOSelectionViewController_Impl.h; sourceTree = "<group>"; };
+ 689EBB7D1806D22C002F1CD7 /* MLOThesaurusViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOThesaurusViewController.h; sourceTree = "<group>"; };
+ 689EBB7E1806D22C002F1CD7 /* MLOThesaurusViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLOThesaurusViewController.m; sourceTree = "<group>"; };
+ 689EBB801806D22C002F1CD7 /* MLOFinder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOFinder.h; sourceTree = "<group>"; };
+ 689EBB811806D22C002F1CD7 /* MLOFinder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLOFinder.m; sourceTree = "<group>"; };
+ 689EBB821806D22C002F1CD7 /* MLOToolbarButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOToolbarButton.h; sourceTree = "<group>"; };
+ 689EBB831806D22C002F1CD7 /* MLOToolbarButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLOToolbarButton.m; sourceTree = "<group>"; };
+ 689EBB841806D22D002F1CD7 /* MLOToolbarViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOToolbarViewController.h; sourceTree = "<group>"; };
+ 689EBB851806D22D002F1CD7 /* MLOToolbarViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLOToolbarViewController.m; sourceTree = "<group>"; };
+ 68FDBE2A18053A140064DD74 /* libios_sharedlo.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libios_sharedlo.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ 68FDBE2D18053A140064DD74 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 68FDBE3118053A140064DD74 /* ios_sharedlo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ios_sharedlo-Prefix.pch"; sourceTree = "<group>"; };
+ 68FDBE3218053A140064DD74 /* ios_sharedlo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ios_sharedlo.h; path = ../ios_sharedlo.h; sourceTree = "<group>"; };
+ 68FDBE3418053A140064DD74 /* ios_sharedlo.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ios_sharedlo.m; path = ../ios_sharedlo.m; sourceTree = "<group>"; };
+ 88A2ED21180D4D7C009F39C0 /* MLOKeyboardManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLOKeyboardManager.h; sourceTree = "<group>"; };
+ 88A2ED22180D4D7C009F39C0 /* MLOKeyboardManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLOKeyboardManager.m; sourceTree = "<group>"; };
+ 88E94760180D4E9800771808 /* MLOToolbarViewController_Impl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MLOToolbarViewController_Impl.h; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 68FDBE2718053A140064DD74 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 68FDBE2E18053A140064DD74 /* Foundation.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 688EAAF8180D6773003741B3 /* Config */ = {
+ isa = PBXGroup;
+ children = (
+ 689EBADD1806975D002F1CD7 /* lo.xcconfig */,
+ );
+ name = Config;
+ sourceTree = "<group>";
+ };
+ 689EBB301806D221002F1CD7 /* cxx */ = {
+ isa = PBXGroup;
+ children = (
+ 689EBB311806D221002F1CD7 /* mlo.h */,
+ 689EBB321806D221002F1CD7 /* mlo.mm */,
+ 689EBB331806D221002F1CD7 /* mlo_uno.h */,
+ 689EBB341806D221002F1CD7 /* mlo_uno.mm */,
+ 689EBB351806D221002F1CD7 /* mlo_utils.h */,
+ 689EBB361806D221002F1CD7 /* mlo_utils.mm */,
+ 689EBB371806D221002F1CD7 /* time.h */,
+ );
+ path = cxx;
+ sourceTree = "<group>";
+ };
+ 689EBB3B1806D22C002F1CD7 /* objective_c */ = {
+ isa = PBXGroup;
+ children = (
+ 689EBB3C1806D22C002F1CD7 /* gestures */,
+ 689EBB471806D22C002F1CD7 /* render */,
+ 689EBB531806D22C002F1CD7 /* utils */,
+ 689EBB631806D22C002F1CD7 /* view_controllers */,
+ 689EBB441806D22C002F1CD7 /* MLOInvoker.h */,
+ 689EBB451806D22C002F1CD7 /* MLOManager.h */,
+ 689EBB461806D22C002F1CD7 /* MLOManager.m */,
+ 68FDBE3218053A140064DD74 /* ios_sharedlo.h */,
+ 68FDBE3418053A140064DD74 /* ios_sharedlo.m */,
+ );
+ path = objective_c;
+ sourceTree = "<group>";
+ };
+ 689EBB3C1806D22C002F1CD7 /* gestures */ = {
+ isa = PBXGroup;
+ children = (
+ 689EBB3D1806D22C002F1CD7 /* MLOGestureEngine.h */,
+ 689EBB3E1806D22C002F1CD7 /* MLOGestureEngine.m */,
+ 689EBB3F1806D22C002F1CD7 /* MLOGestureEngine_Impl.h */,
+ 689EBB401806D22C002F1CD7 /* MLOGestureFlick.h */,
+ 689EBB411806D22C002F1CD7 /* MLOGestureFlick.m */,
+ 689EBB421806D22C002F1CD7 /* MLOGestureLimiter.h */,
+ 689EBB431806D22C002F1CD7 /* MLOGestureLimiter.m */,
+ 88A2ED21180D4D7C009F39C0 /* MLOKeyboardManager.h */,
+ 88A2ED22180D4D7C009F39C0 /* MLOKeyboardManager.m */,
+ );
+ path = gestures;
+ sourceTree = "<group>";
+ };
+ 689EBB471806D22C002F1CD7 /* render */ = {
+ isa = PBXGroup;
+ children = (
+ 689EBB481806D22C002F1CD7 /* MLOPostRenderManager.h */,
+ 689EBB491806D22C002F1CD7 /* MLOPostRenderManager.m */,
+ 689EBB4A1806D22C002F1CD7 /* MLORenderBuffer.h */,
+ 689EBB4B1806D22C002F1CD7 /* MLORenderBuffer.m */,
+ 689EBB4C1806D22C002F1CD7 /* MLORenderingUIView.h */,
+ 689EBB4D1806D22C002F1CD7 /* MLORenderingUIView.m */,
+ 689EBB4E1806D22C002F1CD7 /* MLORenderManager.h */,
+ 689EBB4F1806D22C002F1CD7 /* MLORenderManager.m */,
+ 689EBB501806D22C002F1CD7 /* MLORenderManager_Impl.h */,
+ 689EBB511806D22C002F1CD7 /* MLOScalingBuffer.h */,
+ 689EBB521806D22C002F1CD7 /* MLOScalingBuffer.m */,
+ );
+ path = render;
+ sourceTree = "<group>";
+ };
+ 689EBB531806D22C002F1CD7 /* utils */ = {
+ isa = PBXGroup;
+ children = (
+ 689EBB541806D22C002F1CD7 /* MLOAnimation.h */,
+ 689EBB551806D22C002F1CD7 /* MLOAnimation.m */,
+ 689EBB561806D22C002F1CD7 /* MLOButton.h */,
+ 689EBB571806D22C002F1CD7 /* MLOButton.m */,
+ 689EBB581806D22C002F1CD7 /* MLOCommon.h */,
+ 689EBB591806D22C002F1CD7 /* MLOObject.h */,
+ 689EBB5A1806D22C002F1CD7 /* MLOObject.m */,
+ 689EBB5B1806D22C002F1CD7 /* MLOResourceImage.h */,
+ 689EBB5C1806D22C002F1CD7 /* MLOResourceImage.m */,
+ 689EBB5D1806D22C002F1CD7 /* MLOSubView.h */,
+ 689EBB5E1806D22C002F1CD7 /* MLOSubView.m */,
+ 689EBB5F1806D22C002F1CD7 /* MLOViewController.h */,
+ 689EBB601806D22C002F1CD7 /* MLOViewController.m */,
+ 689EBB611806D22C002F1CD7 /* NSObject+MLOUtils.h */,
+ 689EBB621806D22C002F1CD7 /* NSObject+MLOUtils.m */,
+ );
+ path = utils;
+ sourceTree = "<group>";
+ };
+ 689EBB631806D22C002F1CD7 /* view_controllers */ = {
+ isa = PBXGroup;
+ children = (
+ 689EBB641806D22C002F1CD7 /* MLOMainViewController.h */,
+ 689EBB651806D22C002F1CD7 /* MLOMainViewController.m */,
+ 689EBB661806D22C002F1CD7 /* MLOMainViewController_Impl.h */,
+ 689EBB681806D22C002F1CD7 /* MLOTopbarViewController.h */,
+ 689EBB691806D22C002F1CD7 /* MLOTopbarViewController.m */,
+ 689EBB6A1806D22C002F1CD7 /* scroller */,
+ 689EBB731806D22C002F1CD7 /* selection */,
+ 689EBB7F1806D22C002F1CD7 /* toolbar */,
+ );
+ path = view_controllers;
+ sourceTree = "<group>";
+ };
+ 689EBB6A1806D22C002F1CD7 /* scroller */ = {
+ isa = PBXGroup;
+ children = (
+ 689EBB6B1806D22C002F1CD7 /* MLOScrollerData.h */,
+ 689EBB6C1806D22C002F1CD7 /* MLOScrollerData.m */,
+ 689EBB6D1806D22C002F1CD7 /* MLOScrollerGridViewController.h */,
+ 689EBB6E1806D22C002F1CD7 /* MLOScrollerGridViewController.m */,
+ 689EBB6F1806D22C002F1CD7 /* MLOScrollerTooltip.h */,
+ 689EBB701806D22C002F1CD7 /* MLOScrollerTooltip.m */,
+ 689EBB711806D22C002F1CD7 /* MLOScrollerViewController.h */,
+ 689EBB721806D22C002F1CD7 /* MLOScrollerViewController.m */,
+ );
+ path = scroller;
+ sourceTree = "<group>";
+ };
+ 689EBB731806D22C002F1CD7 /* selection */ = {
+ isa = PBXGroup;
+ children = (
+ 689EBB741806D22C002F1CD7 /* MLOContextualMenuFocus.h */,
+ 689EBB751806D22C002F1CD7 /* MLOContextualMenuFocus.m */,
+ 689EBB761806D22C002F1CD7 /* MLOMagnifier.h */,
+ 689EBB771806D22C002F1CD7 /* MLOMagnifier.m */,
+ 689EBB781806D22C002F1CD7 /* MLOSelectionHandle.h */,
+ 689EBB791806D22C002F1CD7 /* MLOSelectionHandle.m */,
+ 689EBB7A1806D22C002F1CD7 /* MLOSelectionViewController.h */,
+ 689EBB7B1806D22C002F1CD7 /* MLOSelectionViewController.m */,
+ 689EBB7C1806D22C002F1CD7 /* MLOSelectionViewController_Impl.h */,
+ 689EBB7D1806D22C002F1CD7 /* MLOThesaurusViewController.h */,
+ 689EBB7E1806D22C002F1CD7 /* MLOThesaurusViewController.m */,
+ );
+ path = selection;
+ sourceTree = "<group>";
+ };
+ 689EBB7F1806D22C002F1CD7 /* toolbar */ = {
+ isa = PBXGroup;
+ children = (
+ 689EBB801806D22C002F1CD7 /* MLOFinder.h */,
+ 689EBB811806D22C002F1CD7 /* MLOFinder.m */,
+ 689EBB821806D22C002F1CD7 /* MLOToolbarButton.h */,
+ 689EBB831806D22C002F1CD7 /* MLOToolbarButton.m */,
+ 689EBB841806D22D002F1CD7 /* MLOToolbarViewController.h */,
+ 88E94760180D4E9800771808 /* MLOToolbarViewController_Impl.h */,
+ 689EBB851806D22D002F1CD7 /* MLOToolbarViewController.m */,
+ );
+ path = toolbar;
+ sourceTree = "<group>";
+ };
+ 68FDBE2118053A140064DD74 = {
+ isa = PBXGroup;
+ children = (
+ 68FDBE2F18053A140064DD74 /* ios_sharedlo */,
+ 688EAAF8180D6773003741B3 /* Config */,
+ 68FDBE2C18053A140064DD74 /* Frameworks */,
+ 68FDBE2B18053A140064DD74 /* Products */,
+ );
+ sourceTree = "<group>";
+ };
+ 68FDBE2B18053A140064DD74 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 68FDBE2A18053A140064DD74 /* libios_sharedlo.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 68FDBE2C18053A140064DD74 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 68FDBE2D18053A140064DD74 /* Foundation.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ 68FDBE2F18053A140064DD74 /* ios_sharedlo */ = {
+ isa = PBXGroup;
+ children = (
+ 689EBB301806D221002F1CD7 /* cxx */,
+ 689EBB3B1806D22C002F1CD7 /* objective_c */,
+ 68FDBE3018053A140064DD74 /* Supporting Files */,
+ );
+ path = ios_sharedlo;
+ sourceTree = "<group>";
+ };
+ 68FDBE3018053A140064DD74 /* Supporting Files */ = {
+ isa = PBXGroup;
+ children = (
+ 68FDBE3118053A140064DD74 /* ios_sharedlo-Prefix.pch */,
+ );
+ name = "Supporting Files";
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 68FDBE2918053A140064DD74 /* ios_sharedlo */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 68FDBE3818053A140064DD74 /* Build configuration list for PBXNativeTarget "ios_sharedlo" */;
+ buildPhases = (
+ 68FDBE2618053A140064DD74 /* Sources */,
+ 68FDBE2718053A140064DD74 /* Frameworks */,
+ 68FDBE2818053A140064DD74 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = ios_sharedlo;
+ productName = ios_sharedlo;
+ productReference = 68FDBE2A18053A140064DD74 /* libios_sharedlo.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 68FDBE2218053A140064DD74 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0460;
+ ORGANIZATIONNAME = LibreOffice.org;
+ };
+ buildConfigurationList = 68FDBE2518053A140064DD74 /* Build configuration list for PBXProject "ios_sharedlo" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = 68FDBE2118053A140064DD74;
+ productRefGroup = 68FDBE2B18053A140064DD74 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 68FDBE2918053A140064DD74 /* ios_sharedlo */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 68FDBE2618053A140064DD74 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 68FDBE3518053A140064DD74 /* ios_sharedlo.m in Sources */,
+ 689EBB381806D221002F1CD7 /* mlo.mm in Sources */,
+ 689EBB391806D221002F1CD7 /* mlo_uno.mm in Sources */,
+ 689EBB3A1806D221002F1CD7 /* mlo_utils.mm in Sources */,
+ 689EBB861806D22D002F1CD7 /* MLOGestureEngine.m in Sources */,
+ 689EBB871806D22D002F1CD7 /* MLOGestureFlick.m in Sources */,
+ 689EBB881806D22D002F1CD7 /* MLOGestureLimiter.m in Sources */,
+ 689EBB891806D22D002F1CD7 /* MLOManager.m in Sources */,
+ 689EBB8A1806D22D002F1CD7 /* MLOPostRenderManager.m in Sources */,
+ 689EBB8B1806D22D002F1CD7 /* MLORenderBuffer.m in Sources */,
+ 689EBB8C1806D22D002F1CD7 /* MLORenderingUIView.m in Sources */,
+ 689EBB8D1806D22D002F1CD7 /* MLORenderManager.m in Sources */,
+ 689EBB8E1806D22D002F1CD7 /* MLOScalingBuffer.m in Sources */,
+ 689EBB8F1806D22D002F1CD7 /* MLOAnimation.m in Sources */,
+ 689EBB901806D22D002F1CD7 /* MLOButton.m in Sources */,
+ 689EBB911806D22D002F1CD7 /* MLOObject.m in Sources */,
+ 689EBB921806D22D002F1CD7 /* MLOResourceImage.m in Sources */,
+ 689EBB931806D22D002F1CD7 /* MLOSubView.m in Sources */,
+ 689EBB941806D22D002F1CD7 /* MLOViewController.m in Sources */,
+ 689EBB951806D22D002F1CD7 /* NSObject+MLOUtils.m in Sources */,
+ 689EBB961806D22D002F1CD7 /* MLOMainViewController.m in Sources */,
+ 689EBB971806D22D002F1CD7 /* MLOTopbarViewController.m in Sources */,
+ 689EBB981806D22D002F1CD7 /* MLOScrollerData.m in Sources */,
+ 689EBB991806D22D002F1CD7 /* MLOScrollerGridViewController.m in Sources */,
+ 689EBB9A1806D22D002F1CD7 /* MLOScrollerTooltip.m in Sources */,
+ 689EBB9B1806D22D002F1CD7 /* MLOScrollerViewController.m in Sources */,
+ 689EBB9C1806D22D002F1CD7 /* MLOContextualMenuFocus.m in Sources */,
+ 689EBB9D1806D22D002F1CD7 /* MLOMagnifier.m in Sources */,
+ 689EBB9E1806D22D002F1CD7 /* MLOSelectionHandle.m in Sources */,
+ 689EBB9F1806D22D002F1CD7 /* MLOSelectionViewController.m in Sources */,
+ 689EBBA01806D22D002F1CD7 /* MLOThesaurusViewController.m in Sources */,
+ 689EBBA11806D22D002F1CD7 /* MLOFinder.m in Sources */,
+ 689EBBA21806D22D002F1CD7 /* MLOToolbarButton.m in Sources */,
+ 689EBBA31806D22D002F1CD7 /* MLOToolbarViewController.m in Sources */,
+ 88A2ED23180D4D7C009F39C0 /* MLOKeyboardManager.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 68FDBE3618053A140064DD74 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 689EBADD1806975D002F1CD7 /* lo.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libstdc++";
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ ../../include,
+ "$(BUILDDIR)/config_build",
+ "$(BUILDDIR)/workdir/unxiosr.pro/UnoApiHeadersTarget/udkapi/comprehensive",
+ "$(BUILDDIR)/workdir/unxiosr.pro/UnoApiHeadersTarget/offapi/comprehensive",
+ );
+ IPHONEOS_DEPLOYMENT_TARGET = 6.1;
+ LD_NO_PIE = NO;
+ LINK_WITH_STANDARD_LIBRARIES = NO;
+ LLVM_LTO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ };
+ name = Debug;
+ };
+ 68FDBE3718053A140064DD74 /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 689EBADD1806975D002F1CD7 /* lo.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libstdc++";
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ ../../include,
+ "$(BUILDDIR)/config_build",
+ "$(BUILDDIR)/workdir/unxiosr.pro/UnoApiHeadersTarget/udkapi/comprehensive",
+ "$(BUILDDIR)/workdir/unxiosr.pro/UnoApiHeadersTarget/offapi/comprehensive",
+ );
+ IPHONEOS_DEPLOYMENT_TARGET = 6.1;
+ LD_NO_PIE = NO;
+ LINK_WITH_STANDARD_LIBRARIES = NO;
+ LLVM_LTO = YES;
+ SDKROOT = iphoneos;
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 68FDBE3918053A140064DD74 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LIBRARY = "libstdc++";
+ DSTROOT = /tmp/ios_sharedlo.dst;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_LINK_WITH_DYNAMIC_LIBRARIES = NO;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "ios_sharedlo/ios_sharedlo-Prefix.pch";
+ LD_NO_PIE = NO;
+ LINK_WITH_STANDARD_LIBRARIES = NO;
+ OTHER_LDFLAGS = "-ObjC";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SKIP_INSTALL = YES;
+ VALID_ARCHS = armv7;
+ };
+ name = Debug;
+ };
+ 68FDBE3A18053A140064DD74 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LIBRARY = "libstdc++";
+ DSTROOT = /tmp/ios_sharedlo.dst;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_LINK_WITH_DYNAMIC_LIBRARIES = NO;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "ios_sharedlo/ios_sharedlo-Prefix.pch";
+ LD_NO_PIE = NO;
+ LINK_WITH_STANDARD_LIBRARIES = NO;
+ OTHER_LDFLAGS = "-ObjC";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SKIP_INSTALL = YES;
+ VALID_ARCHS = armv7;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 68FDBE2518053A140064DD74 /* Build configuration list for PBXProject "ios_sharedlo" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 68FDBE3618053A140064DD74 /* Debug */,
+ 68FDBE3718053A140064DD74 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 68FDBE3818053A140064DD74 /* Build configuration list for PBXNativeTarget "ios_sharedlo" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 68FDBE3918053A140064DD74 /* Debug */,
+ 68FDBE3A18053A140064DD74 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 68FDBE2218053A140064DD74 /* Project object */;
+}
diff --git a/ios/shared/ios_sharedlo/cxx/mlo.h b/ios/shared/ios_sharedlo/cxx/mlo.h
new file mode 100644
index 000000000000..5055c3a633d6
--- /dev/null
+++ b/ios/shared/ios_sharedlo/cxx/mlo.h
@@ -0,0 +1,19 @@
+// -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ void mlo_initialize(void);
+ #ifdef __cplusplus
+}
+#endif
+
+// vim:set shiftwidth=4 softtabstop=4 expandtab:
+
diff --git a/ios/shared/ios_sharedlo/cxx/mlo.mm b/ios/shared/ios_sharedlo/cxx/mlo.mm
new file mode 100644
index 000000000000..478e012f8cb4
--- /dev/null
+++ b/ios/shared/ios_sharedlo/cxx/mlo.mm
@@ -0,0 +1,219 @@
+// -*- Mode: ObjC; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOCommon.h"
+//#include <stdlib.h>
+
+#include <premac.h>
+#import <UIKit/UIKit.h>
+#include <postmac.h>
+
+#include <osl/detail/component-mapping.h>
+#include <touch/touch.h>
+#undef TimeValue
+#include <osl/process.h>
+
+#define ADD_LIB(LIB) extern void * LIB##_component_getFactory( const char * pImplName, void * pServiceManager, void * pRegistryKey )
+#define MAP_LIB(LIB) { "lib" #LIB ".a", LIB##_component_getFactory }
+#define MAP_LIB_LO(LIB) { "lib" #LIB "lo.a", LIB##_component_getFactory }
+#define MAP_LIB_LO_1(LIB) { "lib" #LIB "lo.a", LIB##1_component_getFactory }
+
+extern "C" {
+
+ //from iOS
+
+ //ADD_LIB(analysis); // Exotic calc functionality
+ //ADD_LIB(animcore); // animation support lib
+ //ADD_LIB(avmedia); // video support lib *
+ //ADD_LIB(dba); // dbaccess lib
+ //ADD_LIB(date); // Extra calc functionallty
+
+ //ADD_LIB(dbaxml); // dbaccess lib
+ ADD_LIB(evtatt); // basic event handling
+ ADD_LIB(fileacc); // Simple file access func
+ //ADD_LIB(frm); // form control in documents
+ ADD_LIB(fsstorage); // part of svl required when editing file
+ ADD_LIB(stocservices);
+ ADD_LIB(reflection);
+
+ //ADD_LIB(fwk); // framework toolbars, menu etc. * (Loaded by shlib.cxx)
+ ADD_LIB(fwl); // framework toolbars, menu etc. needed for select all (Creating XDispatchHelper)
+ //ADD_LIB(fwm); // framework toolbars, menu etc.
+ //ADD_LIB(hwp); // Korean Hangul Word Processor file format support
+
+ ADD_LIB(hyphen); // Hunspell - spell checker external lib
+ ADD_LIB(lng); // Linguistic
+ ADD_LIB(lnth); // Linguistic
+ ADD_LIB(oox); // Word open XML func
+
+ //ADD_LIB(pricing); // Calc pricing func
+ //ADD_LIB(sc); // Spreadsheet code
+ //ADD_LIB(scd); // Spreadsheet code
+ //ADD_LIB(scfilt); // Spreadsheet code
+
+ //ADD_LIB(sd); // Impress draw
+ //ADD_LIB(sdd); // Impress Draw
+ //ADD_LIB(sm); // Furmula editor code for writer
+ //ADD_LIB(smd); // Furmula editor code for writer
+
+ ADD_LIB(spell); // Spelling
+ //ADD_LIB(svgfilter); // svg vector graphic filter
+ ADD_LIB(svt); // used for displaying images in writer
+ ADD_LIB(svx);
+
+ ADD_LIB(sw); // wirter code
+ ADD_LIB(swd); // writer code
+ //ADD_LIB(t602filter); // Graphic filters (russian notes)
+ //ADD_LIB(textfd); // Filter
+ //ADD_LIB(xmlfd); // Filter
+ //ADD_LIB(filterconfig1); // Filter *
+
+ ADD_LIB(unoxml); // UNO wrappers for XML services.
+ ADD_LIB(unordf); // UNO wrappers for XML services.
+ ADD_LIB(uui); // Interction handler for vcl
+ ADD_LIB(xmlsecurity); // Stuff for document signing.
+
+ ADD_LIB(xo); // odf filter writer stop working need to fix
+ ADD_LIB(xof); // odf filter writer stop working need to fix
+
+ // from ANDROID
+
+ //ADD_LIB(cui); // extra dialogs *
+ //ADD_LIB(basprov); // Basic scripting
+ //ADD_LIB(chartcore); // Chart implementation for LibreOffice Calc.
+ //ADD_LIB(dlgprov); // Code for embedding objects into LibreOffice
+
+ ADD_LIB(embobj); // needed for embeded objects
+ ADD_LIB(emboleobj); // needed for embeded objects
+ ADD_LIB(expwrap); // Wrapper around expat using UNO.
+ ADD_LIB(fastsax); // Wrapper around expat using UNO.
+ //ADD_LIB(protocolhandler); // Scripting
+
+ //ADD_LIB(sb); // StarBasic * (tied to writer)
+ //ADD_LIB(scriptframe);
+ ADD_LIB(sot); // Compound file storage tools code. *
+ //ADD_LIB(svxcore); // Contains graphics related helper code *
+ //ADD_LIB(spl); // Basic LibreOffice code *
+
+ //ADD_LIB(stringresource);
+ //ADD_LIB(tk); // "Abstract" windowing thing, UNO implementations windowing stuff *
+ //ADD_LIB(ucppkg1); // Content broker (conversion master)
+ //ADD_LIB(vbaswobj); // vba writer support
+ //ADD_LIB(vbaevents); // scripting support
+
+ //ADD_LIB(wpftdraw); // Wordperfect filter
+ //ADD_LIB(wpftwriter); // Wordperfect filter
+
+ ADD_LIB(writerfilter); // Import filter for doc, docx, rtf
+ //ADD_LIB(canvasfactory); // UNO-based graphics backend
+ //ADD_LIB(vclcanvas); // UNO-based graphics backend
+ //ADD_LIB(mtfrenderer); // canvas helper
+
+ // ADDED for search
+
+ ADD_LIB(i18nsearch);
+}
+
+extern "C"
+const lib_to_component_mapping *
+lo_get_libmap(void)
+{
+ static lib_to_component_mapping map[] = {
+
+ //from IOS
+
+ //MAP_LIB_LO(analysis), //MAP_LIB_LO(animcore), //MAP_LIB_LO(sm),
+ //MAP_LIB_LO(avmedia), //MAP_LIB_LO(dba), //MAP_LIB_LO(date),
+ //MAP_LIB_LO(fwk), //MAP_LIB_LO(fwm), //MAP_LIB_LO(frm),
+ //MAP_LIB_LO(pricing), //MAP_LIB_LO(scd), //MAP_LIB_LO(scfilt),
+ //MAP_LIB_LO(hwp),
+ MAP_LIB_LO(hyphen),
+ //MAP_LIB_LO(dbaxml), //MAP_LIB_LO(sdd), //MAP_LIB_LO(smd),
+ MAP_LIB_LO(spell),
+ //MAP_LIB_LO(svgfilter),//MAP_LIB_LO(t602filter),//MAP_LIB_LO(textfd),
+ MAP_LIB_LO(uui),
+ //MAP_LIB_LO(xmlfd),
+ MAP_LIB(xmlsecurity), //MAP_LIB_LO(sc), //MAP_LIB_LO(sd),
+ MAP_LIB_LO(svx), MAP_LIB_LO(fwl), MAP_LIB_LO(oox),
+ MAP_LIB(fileacc), MAP_LIB_LO(svt), MAP_LIB_LO(xof),
+ MAP_LIB_LO(evtatt), MAP_LIB_LO(fsstorage), MAP_LIB_LO(lng),
+ MAP_LIB_LO(swd), MAP_LIB_LO(sw), MAP_LIB_LO(lnth),
+ MAP_LIB_LO(unordf), MAP_LIB_LO(unoxml), MAP_LIB_LO(xo),
+ MAP_LIB_LO(stocservices), MAP_LIB_LO(reflection),
+
+ // from ANDROID
+
+ //MAP_LIB_LO(cui), //MAP_LIB_LO(basprov), //MAP_LIB_LO(chartcore),
+ //MAP_LIB_LO(dlgprov), //MAP_LIB_LO(vclcanvas),//MAP_LIB_LO(sb),
+ //MAP_LIB(scriptframe), //MAP_LIB_LO(vbaevents),
+ //MAP_LIB_LO(spl), //MAP_LIB_LO(tk), //MAP_LIB_LO(stringresource),
+ //MAP_LIB(ucppkg1), //MAP_LIB_LO(vbaswobj), //MAP_LIB_LO(wpftwriter),
+ //MAP_LIB_LO(wpftdraw), //MAP_LIB_LO(svxcore), //MAP_LIB_LO(protocolhandler),
+ //MAP_LIB_LO_1(filterconfig), //MAP_LIB_LO(canvasfactory), //MAP_LIB_LO(mtfrenderer),
+ MAP_LIB_LO(expwrap), MAP_LIB_LO(fastsax), MAP_LIB_LO(writerfilter),
+ MAP_LIB(embobj), MAP_LIB(emboleobj), MAP_LIB_LO(sot),
+
+ // ADDED for search
+
+ MAP_LIB_LO(i18nsearch),
+
+ { NULL, NULL }
+ };
+
+ return map;
+}
+
+
+NSString * createPaths(NSString * base,NSString * appRootEscaped,NSArray * fileNames){
+ NSString * prefix = @"file://";
+ BOOL first = YES;
+
+ for (NSString * fileName in fileNames) {
+
+ base = [base stringByAppendingString: prefix];
+
+ base = [base stringByAppendingString: [appRootEscaped stringByAppendingPathComponent: fileName]];
+
+ if(first){
+ prefix = [@" " stringByAppendingString:prefix];
+ first = NO;
+ }
+ }
+
+ return base;
+}
+
+
+extern "C"
+void
+mlo_initialize(void)
+{
+ NSString * bundlePath = [[NSBundle mainBundle] bundlePath];
+
+ NSString * app_root_escaped = [bundlePath stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
+
+ NSString * uno_types = createPaths(@"-env:UNO_TYPES=", app_root_escaped, @[@"offapi.rdb", @"oovbaapi.rdb",@"udkapi.rdb"]);
+
+ NSString * uno_services = createPaths(@"-env:UNO_SERVICES=", app_root_escaped, @[@"ure/services.rdb", @"services.rdb"]);
+
+
+ const char *argv[] = {
+
+ // "-SAL_LOG=+WARN+INFO",
+ [[bundlePath stringByAppendingPathComponent: @"Viewer"] UTF8String],
+ "-env:URE_INTERNAL_LIB_DIR=file:///",
+ [uno_types UTF8String],
+ [uno_services UTF8String],"--writer"};
+
+ const int argc = sizeof(argv)/sizeof(*argv);
+
+ osl_setCommandArgs(argc, (char **) argv);
+}
+
+
+
diff --git a/ios/shared/ios_sharedlo/cxx/mlo_uno.h b/ios/shared/ios_sharedlo/cxx/mlo_uno.h
new file mode 100644
index 000000000000..d9ec63bcc3ff
--- /dev/null
+++ b/ios/shared/ios_sharedlo/cxx/mlo_uno.h
@@ -0,0 +1,30 @@
+// -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef __LibreOffice_mlo_uno__
+#define __LibreOffice_mlo_uno__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ typedef enum {MARK_ALL,MARK_FIRST,MARK_NEXT,MARK_PREVIOUS} MLOFindSelectionType;
+
+ BOOL mlo_is_document_open(void);
+ BOOL mlo_open_file(NSString * file);
+ void mlo_close(void);
+ long mlo_get_pages(BOOL last);
+ int mlo_find(NSString * toSearch,MLOFindSelectionType type);
+ void mlo_get_selection(NSMutableString * mutableString);
+ void mlo_fetch_view_data(NSMutableString * mutableString);
+ void mlo_select_all(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* defined(__LibreOffice_mlo_uno__) */
diff --git a/ios/shared/ios_sharedlo/cxx/mlo_uno.mm b/ios/shared/ios_sharedlo/cxx/mlo_uno.mm
new file mode 100644
index 000000000000..f75fe1a455bf
--- /dev/null
+++ b/ios/shared/ios_sharedlo/cxx/mlo_uno.mm
@@ -0,0 +1,480 @@
+// -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "mlo_uno.h"
+#import "MLOCommon.h"
+//#include <stdlib.h>
+
+#include <premac.h>
+#import <UIKit/UIKit.h>
+#include <postmac.h>
+
+#undef TimeValue
+#include <osl/process.h>
+
+#include "cppuhelper/bootstrap.hxx"
+#include "com/sun/star/lang/XMultiServiceFactory.hpp"
+#include "com/sun/star/lang/XComponent.hpp"
+#include "com/sun/star/frame/Desktop.hpp"
+#include "com/sun/star/frame/XFrame.hpp"
+#include "com/sun/star/frame/XDispatchProvider.hpp"
+#include "com/sun/star/frame/XDispatchHelper.hpp"
+#include <com/sun/star/frame/DispatchHelper.hpp>
+#include "com/sun/star/frame/XComponentLoader.hpp"
+#include "com/sun/star/awt/XScrollBar.hpp"
+#include <com/sun/star/container/XContentEnumerationAccess.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
+#include <com/sun/star/text/XPageCursor.hpp>
+#include <com/sun/star/text/XTextDocument.hpp>
+#include <com/sun/star/text/XTextRange.hpp>
+#include <com/sun/star/text/XTextTable.hpp>
+#include <com/sun/star/text/XText.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/text/XTextViewCursorSupplier.hpp>
+#include <com/sun/star/table/XCell.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/document/XViewDataSupplier.hpp>
+#include <com/sun/star/util/XSearchable.hpp>
+#include <com/sun/star/util/XSearchDescriptor.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <com/sun/star/uno/XInterface.hpp>
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::awt;
+using namespace com::sun::star::view;
+using namespace com::sun::star::util;
+using namespace com::sun::star::container;
+using namespace com::sun::star::document;
+using namespace com::sun::star::text;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::frame;
+using namespace com::sun::star::beans;
+using namespace cppu;
+
+
+#define OU(C_STRING) OUString::createFromAscii(C_STRING)
+
+#define LOG_EVAL(REF,NS_STRING) REF.get() ? NSLog(@"%@ created",NS_STRING) : NSLog(@"%@ is null",NS_STRING)
+
+// singletons
+
+Reference<XComponentContext> openedComponentContext;
+Reference<XMultiComponentFactory> openedXComponentFactory;
+Reference<XInterface> openedXDesktop;
+Reference < XComponentLoader > openedXComponentLoader;
+
+// document singletons
+
+Reference<XComponent> openedXComponent;
+Reference<XModel> openedXModel;
+Reference<XTextViewCursorSupplier> openedXTextViewCursorSupplier;
+Reference<XController> openedXController;
+Reference<XPageCursor> openedXPageCursor;
+Reference<XViewDataSupplier> openedXViewDataSupplier;
+Reference<XSearchable> openedXSearchable;
+Reference<XSelectionSupplier> openedXSelectionSupplier;
+Reference<XFrame> openedXFrame;
+Reference<XDispatchProvider> openedXDispatchProvider;
+
+Reference<XIndexAccess> currentFindAll;
+rtl::OUString lastSearch;
+::sal_Int32 lastSearchIndex =-1;
+
+/// functions
+
+Reference< XComponentContext > getXComponentContext(){
+ if(!openedComponentContext.get()){
+ openedComponentContext.set(cppu::defaultBootstrap_InitialComponentContext());
+
+ LOG_EVAL(openedComponentContext,@"XComponentContext");
+ }
+ return openedComponentContext;
+}
+
+Reference<XMultiComponentFactory> getXComponentFactory(){
+ if(!openedXComponentFactory.get()){
+ openedXComponentFactory.set(getXComponentContext()->getServiceManager());
+
+ LOG_EVAL(openedXComponentFactory,@"XMultiComponentContext");
+ }
+
+ return openedXComponentFactory;
+}
+
+Reference<XInterface> getXDesktop(){
+ if(!openedXDesktop.get()){
+
+ openedXDesktop.set(getXComponentFactory()->createInstanceWithContext ( OU("com.sun.star.frame.Desktop"), getXComponentContext()));
+
+ LOG_EVAL(openedXDesktop, @"XDesktop");
+ }
+
+ return openedXDesktop;
+}
+
+Reference <XComponentLoader> getXComponentLoader(){
+ if(!openedXComponentLoader.get()){
+ openedXComponentLoader.set(Reference < XComponentLoader >( Desktop::create(getXComponentContext())));
+
+ LOG_EVAL(openedXComponentLoader, @"XComponentLoader");
+ }
+
+ return openedXComponentLoader;
+}
+
+Reference<XModel> getXModel(){
+ if(!openedXModel.get()){
+ Reference<XModel> model(openedXComponent.get(), UNO_QUERY);
+
+ openedXModel.set(model);
+
+ LOG_EVAL(openedXModel, @"XModel");
+ }
+ return openedXModel;
+}
+
+Reference<XController> getXController(){
+ if(!openedXController.get()){
+
+ openedXController.set(getXModel()->getCurrentController());
+
+ LOG_EVAL(openedXController, @"XController");
+
+ }
+ return openedXController;
+}
+
+Reference<XTextViewCursorSupplier> getXTextViewCursorSupplier(){
+ if(!openedXTextViewCursorSupplier.get()){
+
+ Reference<XTextViewCursorSupplier> supplier(getXController(), UNO_QUERY);
+ openedXTextViewCursorSupplier.set(supplier);
+
+ LOG_EVAL(openedXTextViewCursorSupplier, @"XTextViewCursorSupplier");
+ }
+ return openedXTextViewCursorSupplier;
+}
+
+Reference<XPageCursor> getXPageCursor(){
+ if(!openedXPageCursor.get()){
+ Reference<XPageCursor> cursor(getXTextViewCursorSupplier()->getViewCursor(), UNO_QUERY);
+ openedXPageCursor.set(cursor);
+
+ LOG_EVAL(openedXPageCursor, @"XPageCursor");
+ }
+ return openedXPageCursor;
+}
+
+Reference<XViewDataSupplier> getXViewDataSupplier(){
+ //if(!openedXViewDataSupplier.get()){
+ Reference<XViewDataSupplier> supplier(getXController(),UNO_QUERY);
+
+ openedXViewDataSupplier.set(supplier);
+
+ LOG_EVAL(openedXViewDataSupplier,@"XViewDataSupplier");
+ //}
+
+
+ return openedXViewDataSupplier;
+}
+
+Reference<XSearchable> getXSearchable(){
+ if(!openedXSearchable.get()){
+ Reference<XSearchable> xSearchable(getXModel(),UNO_QUERY);
+ openedXSearchable.set(xSearchable);
+
+ LOG_EVAL(openedXSearchable,@"XSearchable");
+ }
+ return openedXSearchable;
+}
+
+Reference<XSelectionSupplier> getXSelectionSupplier(){
+ if(!openedXSelectionSupplier.get()){
+ Reference<XSelectionSupplier> supplier(getXController(),UNO_QUERY);
+ openedXSelectionSupplier.set(supplier);
+
+ LOG_EVAL(openedXSelectionSupplier, @"XSelectionSupplier");
+ }
+ return openedXSelectionSupplier;
+}
+
+Reference<XFrame> getXFrame(){
+ if(!openedXFrame.get()){
+ openedXFrame.set(getXController()->getFrame());
+ LOG_EVAL(openedXFrame, @"XFrame");
+ }
+ return openedXFrame;
+}
+
+Reference<XDispatchProvider> getXDispatchProvider(){
+ if(!openedXDispatchProvider.get()){
+ Reference<XDispatchProvider> provider(getXFrame(),UNO_QUERY);
+ openedXDispatchProvider.set(provider);
+ LOG_EVAL(openedXDispatchProvider, @"XDispatchProvider");
+ }
+ return openedXDispatchProvider;
+}
+
+Reference<XDispatchHelper> getXDispatchHelper(){
+ Reference<XDispatchHelper> helper = DispatchHelper::create(getXComponentContext());
+ LOG_EVAL(helper, @"XDispatchHelper");
+ return helper;
+}
+
+NSString * createFileUri(NSString * file){
+ if(file==nil){
+ NSString * app_root_escaped = [[[NSBundle mainBundle] bundlePath] stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
+ file = [app_root_escaped stringByAppendingPathComponent:@"test1.odt"];
+ } else {
+ file = [file stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
+ }
+ static NSString * prefix = @"file://";
+
+ if(![file hasPrefix:prefix]){
+ return [prefix stringByAppendingString:file];
+ }
+ return file;
+}
+
+void postOpenUnoInitialization(){
+ getXController();
+ getXSearchable();
+}
+
+
+extern "C"
+BOOL
+mlo_open_file(NSString* filepath){
+
+ static const OUString TARGET = OU("_default");
+ static const Sequence<PropertyValue> PROPS (0);
+
+ filepath = createFileUri(filepath);
+ NSLog(@"LO : Opening the file : %@",filepath );
+
+ NSDate * loadStart = [NSDate date];
+ getXDesktop();
+
+ openedXComponent.set(getXComponentLoader()->loadComponentFromURL(OU([filepath UTF8String]),TARGET,0,PROPS));
+
+ if(openedXComponent.get()){
+ NSLog(@"LO : XComponent opened succesffully. Duration: %f",[[NSDate date] timeIntervalSinceDate:loadStart]);
+ postOpenUnoInitialization();
+ NSLog(@"LO : created document singletons");
+ return YES;
+ }
+
+ return NO;
+}
+
+void setLastSearch(OUString string){
+ lastSearch = string;
+ lastSearchIndex = -1;
+ currentFindAll.clear();
+}
+
+void resetLastSearch(){
+ setLastSearch(OUString());
+}
+
+void convert(const OUString & source,NSMutableString * target){
+
+ OString asOString = OUStringToOString( source, RTL_TEXTENCODING_ASCII_US );
+
+ [target setString:[NSString stringWithUTF8String:asOString.getStr()]];
+}
+
+BOOL isResetSearch(NSString * toSearch){
+ if(!toSearch || ([toSearch length] ==0)){
+ resetLastSearch();
+ return YES;
+ }
+ return NO;
+}
+
+void markFind(int searchIndex){
+ Any currentFind= currentFindAll.get()->getByIndex(searchIndex);
+
+ getXSelectionSupplier()->select(currentFind);
+}
+
+void markDeltaFind(int findCount,int delta){
+
+ lastSearchIndex += delta;
+ if(lastSearchIndex == findCount){
+ lastSearchIndex=0;
+ }else if(lastSearchIndex < 0){
+ lastSearchIndex = findCount-1;
+ }
+ markFind(lastSearchIndex);
+}
+
+void markAllFinds(int findCount){
+ for (int i = 0; i<findCount; i++) {
+ markFind(i);
+ }
+}
+
+void setCurrentFindAll(NSString * toSearch){
+ const OUString current = OU([toSearch UTF8String]);
+
+ if(!lastSearch.equals(current)){
+
+ setLastSearch(current);
+ Reference<XSearchDescriptor> descriptor = getXSearchable()->createSearchDescriptor();
+ descriptor->setSearchString(current);
+ currentFindAll.set(getXSearchable()->findAll(descriptor));
+ }
+}
+
+extern "C"
+void
+mlo_close(void){
+
+ if(openedXComponent.get()){
+
+ NSLog(@"Disposing of the XComponent for the opened document");
+
+ openedXComponent->dispose();
+ openedXComponent.clear();
+ openedXModel.clear();
+ openedXTextViewCursorSupplier.clear();
+ openedXController.clear();
+ openedXPageCursor.clear();
+ openedXViewDataSupplier.clear();
+ openedXSearchable.clear();
+ openedXSelectionSupplier.clear();
+ openedXFrame.clear();
+ openedXDispatchProvider.clear();
+ resetLastSearch();
+
+ NSLog(@"XComponent disposed successfully");
+ }
+}
+
+long getLong(Reference<XPropertySet> & set,const OUString & name){
+
+ if(set.get()){
+
+ return set->getPropertyValue(name).get<long>();
+ }
+ return -666;
+
+}
+
+
+int getInt(Reference<XPropertySet> & set,const OUString & name){
+
+ return getLong(set, name);
+
+}
+
+
+extern "C"
+void mlo_fetch_view_data(NSMutableString * mutableString){
+
+ Any any = getXController()->getViewData();
+
+ OUString ou = any.get<OUString>();
+
+ convert(ou, mutableString);
+}
+
+extern "C"
+long
+mlo_get_pages(BOOL last){
+
+ if(last){
+
+ static const OUString PAGE_COUNT = OU("PageCount");
+
+ Reference< XPropertySet > set( getXController(), UNO_QUERY );
+ return getLong(set,PAGE_COUNT);
+ }
+
+
+ return getXPageCursor()->getPage();
+}
+
+
+extern "C"
+int
+mlo_find(NSString * toSearch,MLOFindSelectionType type){
+
+ if(!isResetSearch(toSearch)){
+
+ setCurrentFindAll(toSearch);
+
+ if(currentFindAll.get()){
+ sal_Int32 count =currentFindAll.get()->getCount();
+ if(count>0){
+ switch (type) {
+ case MARK_ALL:
+ // mark all returns total count;
+ markAllFinds(count);
+ return count;
+ case MARK_FIRST:
+ // mark first returns total count
+ // index will be zero
+ markDeltaFind(count,1);
+ return count;
+ case MARK_NEXT:
+ // mark next returns the index
+ markDeltaFind(count, 1);
+ return lastSearchIndex;
+ case MARK_PREVIOUS:
+ // mark previous returns the last index
+ markDeltaFind(count, -1);
+ return lastSearchIndex;
+ }
+ }
+ }
+ }
+ return -1;
+}
+
+extern "C"
+void
+mlo_get_selection(NSMutableString * mutableString){
+ OUString asOuString;
+
+ Reference<XInterface> currentSelection = getXModel()->getCurrentSelection();
+
+ if(currentSelection.get()){
+
+ Reference< XIndexAccess > xIndexAccess( currentSelection, UNO_QUERY );
+
+ if(xIndexAccess.get() && (xIndexAccess->getCount()>0)){
+ Reference< XTextRange > xTextRange(xIndexAccess->getByIndex(0),UNO_QUERY);
+ if(xTextRange.get()){
+ asOuString=xTextRange->getString();
+ }
+ }
+ }
+
+ convert(asOuString, mutableString);
+}
+
+extern "C"
+BOOL
+mlo_is_document_open(void){
+ return openedXComponent.is() ? YES : NO;
+}
+
+extern "C"
+void
+lmo_select_all(void){
+ getXDispatchHelper()->executeDispatch(getXDispatchProvider(),
+ OUString(".uno:SelectAll"),
+ OUString("_self"),
+ 0,
+ Sequence<PropertyValue >());
+} \ No newline at end of file
diff --git a/ios/shared/ios_sharedlo/cxx/mlo_utils.h b/ios/shared/ios_sharedlo/cxx/mlo_utils.h
new file mode 100644
index 000000000000..a2cd5f744478
--- /dev/null
+++ b/ios/shared/ios_sharedlo/cxx/mlo_utils.h
@@ -0,0 +1,22 @@
+// -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef __LibreOffice_mlo_utils__
+#define __LibreOffice_mlo_utils__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ CGFloat max(CGFloat a,CGFloat b);
+ CGFloat min(CGFloat a,CGFloat b);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* defined(__Mobile_LibreOffice_lo_utils__) */
diff --git a/ios/shared/ios_sharedlo/cxx/mlo_utils.mm b/ios/shared/ios_sharedlo/cxx/mlo_utils.mm
new file mode 100644
index 000000000000..07c87fe41de2
--- /dev/null
+++ b/ios/shared/ios_sharedlo/cxx/mlo_utils.mm
@@ -0,0 +1,16 @@
+// -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "mlo_utils.h"
+
+CGFloat max(CGFloat a,CGFloat b){
+ return a>b? a:b;
+}
+CGFloat min(CGFloat a,CGFloat b){
+ return a<b? a:b;
+}
diff --git a/ios/shared/ios_sharedlo/cxx/time.h b/ios/shared/ios_sharedlo/cxx/time.h
new file mode 100644
index 000000000000..c6f727bc7f50
--- /dev/null
+++ b/ios/shared/ios_sharedlo/cxx/time.h
@@ -0,0 +1,159 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you 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 .
+ */
+
+#ifndef _OSL_TIME_H_
+#define _OSL_TIME_H_
+
+#include "sal/config.h"
+
+#include "sal/saldllapi.h"
+#include "sal/types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/****************************************************************************/
+/* TimeValue */
+/****************************************************************************/
+
+#ifdef SAL_W32
+# pragma pack(push, 8)
+#endif
+
+/* Time since Jan-01-1970 */
+
+typedef struct {
+ sal_uInt32 Seconds;
+ sal_uInt32 Nanosec;
+} TimeValueX;
+
+#if defined(SAL_W32)
+# pragma pack(pop)
+#endif
+
+
+/****************************************************************************/
+/* oslDateTime */
+/****************************************************************************/
+
+typedef struct _oslDateTime
+{
+ /*----------------------------------------------------------------------*/
+ /** contains the nanoseconds .
+ */
+ sal_uInt32 NanoSeconds;
+
+ /** contains the seconds (0-59).
+ */
+ sal_uInt16 Seconds;
+
+ /*----------------------------------------------------------------------*/
+ /** contains the minutes (0-59).
+ */
+ sal_uInt16 Minutes;
+
+ /*----------------------------------------------------------------------*/
+ /** contains the hour (0-23).
+ */
+ sal_uInt16 Hours;
+
+ /*----------------------------------------------------------------------*/
+ /** is the day of month (1-31).
+ */
+ sal_uInt16 Day;
+
+ /*----------------------------------------------------------------------*/
+ /** is the day of week (0-6 , 0 : Sunday).
+ */
+ sal_uInt16 DayOfWeek;
+
+ /*----------------------------------------------------------------------*/
+ /** is the month of year (1-12).
+ */
+ sal_uInt16 Month;
+
+ /*----------------------------------------------------------------------*/
+ /** is the year.
+ */
+ sal_uInt16 Year;
+
+} oslDateTime;
+
+
+/** Get the current system time as TimeValue.
+ @return false if any error occurs.
+*/
+SAL_DLLPUBLIC sal_Bool SAL_CALL osl_getSystemTime(
+ TimeValue* pTimeVal );
+
+
+/** Get the GMT from a TimeValue and fill a struct oslDateTime
+ @param[in] pTimeVal TimeValue
+ @param[out] pDateTime On success it receives a struct oslDateTime
+
+ @return sal_False if any error occurs else sal_True.
+*/
+SAL_DLLPUBLIC sal_Bool SAL_CALL osl_getDateTimeFromTimeValue(
+ TimeValue* pTimeVal, oslDateTime* pDateTime );
+
+
+/** Get the GMT from a oslDateTime and fill a TimeValue
+ @param[in] pDateTime oslDateTime
+ @param[out] pTimeVal On success it receives a TimeValue
+
+ @return sal_False if any error occurs else sal_True.
+*/
+SAL_DLLPUBLIC sal_Bool SAL_CALL osl_getTimeValueFromDateTime(
+ oslDateTime* pDateTime, TimeValue* pTimeVal );
+
+
+/** Convert GMT to local time
+ @param[in] pSystemTimeVal system time to convert
+ @param[out] pLocalTimeVal On success it receives the local time
+
+ @return sal_False if any error occurs else sal_True.
+*/
+SAL_DLLPUBLIC sal_Bool SAL_CALL osl_getLocalTimeFromSystemTime(
+ TimeValue* pSystemTimeVal, TimeValue* pLocalTimeVal );
+
+
+/** Convert local time to GMT
+ @param[in] pLocalTimeVal local time to convert
+ @param[out] pSystemTimeVal On success it receives the system time
+
+ @return sal_False if any error occurs else sal_True.
+*/
+SAL_DLLPUBLIC sal_Bool SAL_CALL osl_getSystemTimeFromLocalTime(
+ TimeValue* pLocalTimeVal, TimeValue* pSystemTimeVal );
+
+
+/** Get the value of the global timer
+ @return current timer value in milli seconds
+ */
+
+SAL_DLLPUBLIC sal_uInt32 SAL_CALL osl_getGlobalTimer(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _OSL_TIME_H_ */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/ios/shared/ios_sharedlo/ios_sharedlo-Prefix.pch b/ios/shared/ios_sharedlo/ios_sharedlo-Prefix.pch
new file mode 100644
index 000000000000..bf8cad8036ba
--- /dev/null
+++ b/ios/shared/ios_sharedlo/ios_sharedlo-Prefix.pch
@@ -0,0 +1,8 @@
+//
+// Prefix header for all source files of the 'ios_sharedlo' target in the 'ios_sharedlo' project
+//
+
+#ifdef __OBJC__
+ #import <UIKit/UIKit.h>
+ #import <Foundation/Foundation.h>
+#endif
diff --git a/ios/shared/ios_sharedlo/ios_sharedlo.h b/ios/shared/ios_sharedlo/ios_sharedlo.h
new file mode 100644
index 000000000000..8987fddbafcd
--- /dev/null
+++ b/ios/shared/ios_sharedlo/ios_sharedlo.h
@@ -0,0 +1,13 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import <Foundation/Foundation.h>
+
+@interface ios_sharedlo : NSObject
+
+@end
diff --git a/ios/shared/ios_sharedlo/ios_sharedlo.m b/ios/shared/ios_sharedlo/ios_sharedlo.m
new file mode 100644
index 000000000000..2c09f9be7dde
--- /dev/null
+++ b/ios/shared/ios_sharedlo/ios_sharedlo.m
@@ -0,0 +1,13 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "ios_sharedlo.h"
+
+@implementation ios_sharedlo
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/MLOInvoker.h b/ios/shared/ios_sharedlo/objective_c/MLOInvoker.h
new file mode 100644
index 000000000000..81dc07de32bd
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/MLOInvoker.h
@@ -0,0 +1,21 @@
+//
+// MLOInvoker.h
+// CloudOn_LO_PoC
+//
+// Created by ptyl on 10/3/13.
+// Copyright (c) 2013 CloudOn. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@protocol MLOInvoker <NSObject>
+
+-(void)willShowLibreOffice;
+-(void)didShowLibreOffice;
+
+-(void)willHideLibreOffice;
+-(void)didHideLibreOffice;
+
+-(CGRect) bounds;
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/MLOManager.h b/ios/shared/ios_sharedlo/objective_c/MLOManager.h
new file mode 100644
index 000000000000..04df67703883
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/MLOManager.h
@@ -0,0 +1,27 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOObject.h"
+#import "MLOInvoker.h"
+
+@class MLOMainViewController;
+@interface MLOManager : UIResponder <UIApplicationDelegate,UITextViewDelegate>
+@property (strong,nonatomic) MLOMainViewController * mainViewController;
+
++(MLOManager *) getInstance;
+
+-(BOOL) textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text;
+-(void)openInLibreOfficeFilePath:(NSString *) filePath fileNameWithExtension:(NSString *) fileName superView:(UIView *) superview window:(UIWindow *) window invoker:(NSObject<MLOInvoker> *) invoker;
+-(void)openInLibreOfficeFilePath:(NSString *) filePath superView:(UIView *) superview window:(UIWindow *) window invoker:(NSObject<MLOInvoker> *) invoker;
+-(void) hideLibreOffice;
+-(NSString *)filenameWithExtension;
+-(NSString *)extension;
+-(CGRect)bounds;
+-(void)start;
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/MLOManager.m b/ios/shared/ios_sharedlo/objective_c/MLOManager.m
new file mode 100644
index 000000000000..a422731ee559
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/MLOManager.m
@@ -0,0 +1,215 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOManager.h"
+#import "MLOMainViewController.h"
+#import "MLOInvoker.h"
+#include "touch/touch.h"
+
+#import "mlo.h"
+#import "mlo_uno.h"
+
+#define APP_STUB_DEF (UIApplication *) X { (void) X;}
+
+static MLOManager * instance = nil;
+
+static const NSTimeInterval FADE_IN_DURATION = 0.3;
+
+@interface MLOManager ()
+
+@property NSObject<MLOInvoker> * invoker;
+@property NSString * openedFileNameWithExtension;
+@property NSString * openedFilePath;
+
+@end
+
+@implementation MLOManager
+
+-(id) init{
+ self = [super init];
+
+ if (self) {
+ self.mainViewController = nil;
+ self.invoker = nil;
+ [self resetOpenedFile];
+ }
+ return self;
+}
+
+-(BOOL)isInit{
+ return self.mainViewController != nil;
+}
+
+- (void)applicationDidEnterBackground: APP_STUB_DEF
+- (void)applicationWillEnterForeground: APP_STUB_DEF
+- (void)applicationDidBecomeActive: APP_STUB_DEF
+- (void)applicationWillTerminate: APP_STUB_DEF
+
+
+- (void)applicationWillResignActive:(UIApplication *) application{
+ if (_mainViewController) {
+ [_mainViewController hideLibreOffice];
+ }
+}
+
+-(BOOL)application:(UIApplication *) application didFinishLaunchingWithOptions:(NSDictionary *) launchOptions{
+
+ return YES;
+}
+
+- (void)application:(UIApplication *)application didChangeStatusBarFrame:(CGRect)oldStatusBarFrame
+{
+ IGNORE_ARG(application);
+
+ IGNORE_ARG(oldStatusBarFrame);
+
+ [self.mainViewController rotate];
+}
+
+-(void)start{
+
+ NSLog(@"L O : START LIBRE OFFICE");
+
+ if (![self isInit]) {
+
+ NSLog(@"L O : BEGINNING INITIALIZATION");
+
+ [self initLo];
+
+ NSLog(@"L O : INITIALIZATION COMPLETED!!!");
+ }else{
+ NSLog(@"L O : SKIPPED. ALREADY INITIALIZED.");
+ }
+}
+
++(MLOManager *) getInstance{
+ if(instance ==nil){
+ instance = [self new];
+ }
+ return instance;
+}
+
+-(void) initLo{
+
+ self.mainViewController = [MLOMainViewController new];
+
+ [[[NSThread alloc] initWithTarget:self selector:@selector(threadMainMethod:) object:nil] start];
+
+}
+
+-(void)addLibreOfficeAsSubview:(UIView * ) superview{
+
+ self.mainViewController.view.alpha = 0;
+
+ [superview addSubview: self.mainViewController.view];
+
+ [UIView animateWithDuration:FADE_IN_DURATION animations:^(){
+ self.mainViewController.view.alpha = 1;
+ }];
+}
+
+-(void)showLibreOfficeAfterAddingToSuperView:(UIWindow *) window{
+ window.backgroundColor = [UIColor whiteColor];
+
+ [_mainViewController showLibreOffice:window];
+}
+
+- (void)threadMainMethod:(id)argument
+{
+ IGNORE_ARG(argument);
+
+ @autoreleasepool {
+ NSLog(@"CALLING mlo_initialize");
+
+ mlo_initialize();
+
+ NSLog(@"touch_lo_runMain RETURNED\r\n\r\nCALLING lo_runMain");
+
+ touch_lo_runMain();
+
+ NSLog(@"lo_runMain RETURNED");
+ }
+}
+
+
+- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
+{
+ NSLog(@"textView: %@ shouldChangeTextInRange:[%u,%u] replacementText:%@", textView, range.location, range.length, text);
+
+ int length =[text length];
+
+ for (NSUInteger i = 0; i < length; i++){
+
+ touch_lo_keyboard_input([text characterAtIndex: i]);
+ }
+ if(length>0){
+ [self.mainViewController onTextEdit];
+ }
+
+ return NO;
+}
+-(void) hideLibreOffice{
+
+ [self.invoker willHideLibreOffice];
+
+ mlo_close();
+
+ [self resetOpenedFile];
+
+ [self.mainViewController.view removeFromSuperview];
+
+ [self.invoker didHideLibreOffice];
+
+}
+
+-(CGRect) bounds{
+ return [self.invoker bounds];
+}
+
+-(void)resetOpenedFile{
+ self.openedFileNameWithExtension = nil;
+ self.openedFilePath = nil;
+}
+
+-(void)openInLibreOfficeFilePath:(NSString *) filePath fileNameWithExtension:(NSString *) fileNameWithExtension superView:(UIView *) superview window:(UIWindow *) window invoker:
+(NSObject<MLOInvoker> *) invoker{
+ self.invoker = invoker;
+ self.openedFileNameWithExtension = fileNameWithExtension;
+ self.openedFilePath = filePath;
+ if(mlo_open_file(filePath)){
+ [invoker willShowLibreOffice];
+ [self addLibreOfficeAsSubview:superview];
+ [self showLibreOfficeAfterAddingToSuperView:window];
+ [invoker didShowLibreOffice];
+ }else{
+ [self hideLibreOffice];
+
+ }
+}
+
+-(void)openInLibreOfficeFilePath:(NSString *) filePath superView:(UIView *) superview window:(UIWindow *) window invoker:(NSObject<MLOInvoker> *) invoker{
+ [self openInLibreOfficeFilePath:filePath
+ fileNameWithExtension:[filePath lastPathComponent]
+ superView:superview
+ window:window
+ invoker:invoker];
+}
+
+
+-(NSString *)extension{
+
+ NSString * extension= [self.openedFilePath pathExtension];
+ NSLog(@"File extension is %@",extension);
+ return extension;
+}
+-(NSString *)filenameWithExtension{
+ NSLog(@"Filename with extension is %@",self.openedFileNameWithExtension);
+ return self.openedFileNameWithExtension;
+}
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureEngine.h b/ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureEngine.h
new file mode 100644
index 000000000000..d406b856960c
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureEngine.h
@@ -0,0 +1,19 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOObject.h"
+
+@class MLOMainViewController;
+
+@interface MLOGestureEngine : MLOObject
+-(id)initWithMainViewController:(MLOMainViewController *) mainViewController;
+-(void)showLibreOffice:(UIWindow *) window;
+-(void)hideLibreOffice;
+-(void)reset;
+-(void)onRotate;
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureEngine.m b/ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureEngine.m
new file mode 100644
index 000000000000..51492df6094a
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureEngine.m
@@ -0,0 +1,458 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOAnimation.h"
+#import "MLOMainViewController_Impl.h"
+#import "MLORenderManager_Impl.h"
+#import "MLOSelectionViewController.h"
+#import "MLOScrollerViewController.h"
+#import "MLOGestureFlick.h"
+#import "MLOScrollerData.h"
+#import "MLOGestureLimiter.h"
+#import "MLOGestureEngine_Impl.h"
+#import "MLOKeyboardManager.h"
+#import "mlo.h"
+#import "mlo_utils.h"
+#include <touch/touch.h>
+
+static const CGFloat
+ DOUBLE_TAP_ZOOM_IN=300.0f,
+ DOUBLE_TAP_ZOOM_OUT=100.0f,
+ DOUBLE_TAP_ZOOM_DURATION=0.7f,
+ DOUBLE_TAP_FPS_RATIO=0.5f,
+ DOUBLE_TAP_FPS=50.0f;
+
+static const BOOL ENABLE_LO_EVENTS_DURING_PINCH = NO;
+
+@interface MLOGestureEngine ()
+@property BOOL listening;
+@property BOOL doubleTapped;
+@property NSInteger handledGesturesCount;
+@property CGPoint pinchCenter;
+@property CGPoint panPrevious;
+@property CGPoint dragStart;
+@property NSArray * gestureRecognizers;
+@property UIWindow * window;
+@end
+
+@implementation MLOGestureEngine
+
+-(id)initWithMainViewController:(MLOMainViewController *) mainViewController{
+ self = [self init];
+ if(self){
+ self.mainViewController = mainViewController;
+ self.renderer = [MLORenderManager getInstance];
+ self.selection = mainViewController.selection;
+ self.scroller = mainViewController.scroller;
+ self.flick = [[MLOGestureFlick alloc] initWithEngine:self];
+ self.dragStart= self.panPrevious = self.pinchCenter = CGPointMake(0,0);
+ self.limiter = [[MLOGestureLimiter alloc] initWithGestureEngine:self];
+ self.window = nil;
+ self.focused =NO;
+ self.listening = NO;
+ [self reset];
+ }
+
+ return self;
+}
+
+-(void) createListeners:(UIWindow *) window{
+
+ UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)];
+ UITapGestureRecognizer * doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTap:)];
+ doubleTap.numberOfTapsRequired =2;
+ doubleTap.numberOfTouchesRequired=1;
+ [tap requireGestureRecognizerToFail:doubleTap];
+
+ self.gestureRecognizers = @[tap,
+ doubleTap,
+ [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)],
+ [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(drag:)],
+ [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinch:)]];
+
+
+}
+
+-(void)gestureRecognizersEnable:(BOOL) enable{
+ for(UIGestureRecognizer * recognizer in self.gestureRecognizers){
+ if(enable){
+ [self.window addGestureRecognizer:recognizer];
+ }else{
+ [self.window removeGestureRecognizer:recognizer];
+ }
+ }
+}
+
+-(void)showLibreOffice:(UIWindow *)window{
+
+ self.window = window;
+
+ if(!_listening) {
+
+ [self createListeners:window];
+ _listening = YES;
+ }
+
+ [self gestureRecognizersEnable:YES];
+
+ [_renderer showLibreOffice:self];
+ _focused = YES;
+ [self reset];
+ [self.limiter showLibreOffice];
+}
+
+-(void)hideLibreOffice{
+
+ [self onGestureInterrupt];
+
+ [_renderer hideLibreOffice];
+
+ [_selection reset];
+
+ [self gestureRecognizersEnable:NO];
+
+ self.window = nil;
+
+ _focused = NO;
+}
+
+
+
+-(void)drag:(UILongPressGestureRecognizer *) gesture{
+
+ if(_focused){
+
+ CGPoint point = [gesture locationInView:_renderer.view];
+
+ if([_mainViewController.canvas pointInside:point withEvent:nil]){
+
+ [_selection hide];
+
+ UIGestureRecognizerState state = gesture.state;
+
+ NSLog(@"MLO gesture engine long press state %d in point: (%f,%f)",state ,point.x,point.y);
+
+ if(state == UIGestureRecognizerStateBegan) {
+
+ self.dragStart = point;
+
+ touch_lo_mouse_drag(point.x, point.y, DOWN);
+
+ } else if(state == UIGestureRecognizerStateChanged) {
+
+ touch_lo_mouse_drag(point.x, point.y, MOVE);
+
+ [_selection showBetweenFinger:point andPreviousPoint:self.dragStart showMenu:NO];
+
+ } else if(state == UIGestureRecognizerStateEnded) {
+
+ touch_lo_mouse_drag(point.x, point.y, UP);
+
+ [_selection showBetweenFinger:point andPreviousPoint:self.dragStart showMenu:YES];
+ }
+ [self evalGestureCount: state];
+ }
+ }
+}
+
+- (void)tap:(UITapGestureRecognizer *)gesture
+{
+ [self tapGeneric:gesture name:@"tap" requiresTappable:YES action:^(CGPoint location){
+
+ touch_lo_tap(location.x, location.y);
+
+ [self.mainViewController.keyboard show];
+
+ }];
+
+}
+
+-(void) doubleTap:(UITapGestureRecognizer *)gesture{
+ [self tapGeneric:gesture name:@"double tap" requiresTappable:NO action:^(CGPoint location){
+
+ __block CGFloat initialZoom = [_limiter zoom];
+
+ CGFloat targetZoom = _doubleTapped ? DOUBLE_TAP_ZOOM_OUT : DOUBLE_TAP_ZOOM_IN;
+ CGFloat deltaZoom = targetZoom - initialZoom;
+
+ if(LOG_DOUBLE_TAP){
+ NSLog(@"DoubleTap currentZoom=%f targetZoom=%f",initialZoom,targetZoom);
+ }
+
+ [self pinch:location scale:1.0f state:UIGestureRecognizerStateBegan];
+
+ MLOAnimation * animation=
+ [[MLOAnimation alloc]
+ initWithBehavior: MANDATORY
+ fractionType: FULL_FRACTION
+ animation: ^(CGFloat fraction){
+ [self pinch: location
+ scale: (initialZoom + deltaZoom *fraction)/ initialZoom
+ state: UIGestureRecognizerStateChanged];
+ }];
+
+ animation.fps = DOUBLE_TAP_FPS;
+ animation.duration = DOUBLE_TAP_ZOOM_DURATION;
+ [animation linearCurve];
+ animation.endBlock = ^(void){
+
+ [self pinch:location
+ scale:targetZoom / initialZoom
+ state:UIGestureRecognizerStateEnded];
+
+ };
+ [_currentAnimation cancel];
+ self.currentAnimation = animation;
+
+ [animation animate];
+
+ _doubleTapped^=YES;
+
+ }];
+}
+
+
+-(void)tapGeneric:(UITapGestureRecognizer *) gesture
+ name:(NSString *) name
+ requiresTappable:(BOOL) isRequiresTappable
+ action:(void (^)(CGPoint location)) doTap {
+
+ if(_focused){
+
+ UIGestureRecognizerState state = gesture.state;
+
+ if (state == UIGestureRecognizerStateEnded) {
+
+ [self onGestureInterrupt];
+
+ CGPoint point = [gesture locationInView: _renderer.view];
+
+ if([_mainViewController.canvas pointInside:point withEvent:nil]){
+
+ if(!isRequiresTappable || [_mainViewController isTappable]){
+
+ NSLog(@"%@: at: (%d,%d)",name, (int)point.x, (int)point.y);
+ doTap(point);
+
+ }else{
+ NSLog(@"%@ gesture aborted - main view controller is not tappable",name);
+ }
+ }
+ } else{
+ NSLog(@"%@ Gesture: %@", name, gesture);
+ }
+
+ [self evalGestureCount:state];
+ }
+}
+
+
+-(void)onScroll:(UIGestureRecognizerState) state deltaY:(CGFloat) deltaY{
+ if((state ==UIGestureRecognizerStateEnded)||
+ (state == UIGestureRecognizerStateBegan)){
+ [_scroller updateByLogic];
+ }else{
+ [_scroller updateByPixelDeltaY:deltaY];
+ }
+ [self evalGestureCount: state];
+
+}
+
+
+- (void)pan:(UIPanGestureRecognizer *)gesture{
+ if(_focused){
+
+ CGPoint location = [gesture locationInView:_renderer.view];
+
+ UIGestureRecognizerState state = gesture.state;
+
+ if(![_selection handleMoveAtPoint:location gestureState:state] &&
+ [_mainViewController.canvas pointInside:location withEvent:nil]){
+
+ if(state != UIGestureRecognizerStateBegan){
+
+ NSInteger deltaX = location.x - self.panPrevious.x;
+ NSInteger deltaY = location.y - self.panPrevious.y;
+
+ [self loPanDeltaX:deltaX deltaY:deltaY state:state];
+ }
+
+ [self evalGestureCount:state];
+
+ self.panPrevious = location;
+
+ if(![_flick eval:gesture] &&
+ (state == UIGestureRecognizerStateEnded)){
+
+ [self endPan];
+ }
+
+ }
+ }
+}
+
+-(void)endFlick{
+ [self endPan];
+ [self onScroll:UIGestureRecognizerStateEnded deltaY:0.0f];
+}
+
+-(void) endPan{
+ NSLog(@"PAN ENDED");
+ [_renderer endGestures];
+}
+
+-(BOOL) loPanDeltaX:(NSInteger) rawDeltaX deltaY:(NSInteger) rawDeltaY state:(UIGestureRecognizerState) state{
+
+ CGFloat limitedDeltaX = [_limiter limitDelta:rawDeltaX direction:DELTA_X];
+ CGFloat limitedDeltaY = [_limiter limitDelta:rawDeltaY direction:DELTA_Y];
+
+ if((limitedDeltaX!=0.0f)
+ || (limitedDeltaY!=0.0f)){
+
+ if(LOG_PAN){
+ [_limiter logPanRawDeltaX:rawDeltaX
+ rawDeltaY:rawDeltaY
+ limitedDeltaX:limitedDeltaX
+ limitedDeltaY:limitedDeltaY];
+ }
+
+ [_mainViewController.renderManager panDeltaX:(CGFloat)limitedDeltaX
+ deltaY:(CGFloat)limitedDeltaY];
+
+
+ [self onScroll:state deltaY: limitedDeltaY];
+
+ lo_pan(limitedDeltaX, limitedDeltaY);
+
+ return YES;
+ }
+ return NO;
+}
+
+- (void)pinch:(UIPinchGestureRecognizer *)gesture
+{
+ if(_focused){
+
+ if(gesture.numberOfTouches>1){
+ self.pinchCenter = [gesture locationInView:_renderer.view];
+ }
+
+ [self pinch:self.pinchCenter scale:[gesture scale] state:gesture.state];
+
+ }
+}
+
+-(void)pinch:(CGPoint) location scale:(CGFloat) scale state:(UIGestureRecognizerState) state{
+
+ [_selection hide];
+
+ if(state ==UIGestureRecognizerStateBegan){
+ self.panPrevious = location;
+ [_limiter beginPinch];
+ }else{
+
+ CGFloat scaleRatioToLastScale = [_limiter inPinchGetRatioToLastScale:scale];
+ CGFloat deltaX = (location.x - self.panPrevious.x)*scaleRatioToLastScale;
+ CGFloat deltaY = (location.y - self.panPrevious.y)*scaleRatioToLastScale;
+
+ deltaX = [_limiter limitDelta:deltaX direction:DELTA_X];
+ deltaY = [_limiter limitDelta:deltaY direction:DELTA_Y];
+
+ self.panPrevious = location;
+
+ if(ENABLE_PINCH_RENDERING_VIA_IOS){
+
+ [_renderer pinchDeltaX:deltaX
+ deltaY:deltaY
+ scale:[_limiter currentPinchScale]];
+
+ if(ENABLE_LO_EVENTS_DURING_PINCH){
+ [_limiter fireLoZoomEventsDuringPinch];
+ }
+
+ if(state==UIGestureRecognizerStateEnded){
+
+ CGPoint shift = [_renderer getShiftFromCanvasCenter];
+
+ [_renderer endGestures];
+
+ [self loZoomDeltaX:shift.x
+ deltaY:shift.y
+ scale:[_limiter endPinchAndGetScaleForLo:scale]];
+
+ }
+
+ }else{
+ [self loZoomDeltaX:deltaX deltaY:deltaY scale:scaleRatioToLastScale];
+ }
+ }
+
+ [self onScroll:state deltaY:0];
+}
+-(void)loZoomDeltaX:(CGFloat)deltaX deltaY:(CGFloat)deltaY scale:(CGFloat) scale{
+ NSInteger xInt = deltaX;
+ NSInteger yInt = deltaY;
+
+ if(LOG_PINCH){
+ NSLog(@"touch_lo_zoom: (%d,%d) scale=%f",xInt,yInt, scale);
+ }
+
+ touch_lo_zoom(xInt, yInt, (float)scale);
+}
+
+
+
+-(void)onGestureInterrupt{
+ [_selection hide];
+ [_currentAnimation cancel];
+
+}
+
+-(void)evalGestureCount:(UIGestureRecognizerState) state{
+ if(state == UIGestureRecognizerStateBegan){
+
+ _handledGesturesCount++;
+
+ }else if(state == UIGestureRecognizerStateCancelled ||
+ state == UIGestureRecognizerStateEnded ||
+ state == UIGestureRecognizerStateFailed){
+
+ _handledGesturesCount--;
+
+ if(_handledGesturesCount==0){
+ [_scroller fadeOut];
+ } else if(_handledGesturesCount < 0){
+ self.handledGesturesCount = 0;
+ }
+ }
+}
+
+- (void)onKeyboardShow{
+ if(_focused){
+
+ [_selection hide];
+ }
+}
+
+- (void)onKeyboardHide{
+
+}
+
+-(void)reset{
+ self.doubleTapped = NO;
+ self.handledGesturesCount = 0;
+}
+
+-(void)onRotate{
+ self.handledGesturesCount=0;
+ [_limiter onRotate];
+}
+
+@end
+
+
diff --git a/ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureEngine_Impl.h b/ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureEngine_Impl.h
new file mode 100644
index 000000000000..67002125b523
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureEngine_Impl.h
@@ -0,0 +1,35 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOGestureEngine.h"
+
+@class MLOGestureFlick,
+ MLOMainViewController,
+ MLOSelectionViewController,
+ MLOScrollerViewController,
+ MLOAnimation,
+ MLORenderManager,
+ MLOGestureLimiter;
+
+@interface MLOGestureEngine ()
+
+@property MLOMainViewController * mainViewController;
+@property MLOSelectionViewController * selection;
+@property MLOScrollerViewController * scroller;
+@property MLOAnimation * currentAnimation;
+@property MLOGestureFlick * flick;
+@property MLORenderManager * renderer;
+@property MLOGestureLimiter * limiter;
+@property BOOL focused;
+-(NSInteger) handledGesturesCount;
+-(BOOL) loPanDeltaX:(NSInteger) rawDeltaX deltaY:(NSInteger) rawDeltaY state:(UIGestureRecognizerState) state;
+-(void)loZoomDeltaX:(CGFloat)deltaX deltaY:(CGFloat)deltaY scale:(CGFloat) scale;
+-(void) onKeyboardShow;
+-(void) onKeyboardHide;
+-(void) endFlick;
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureFlick.h b/ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureFlick.h
new file mode 100644
index 000000000000..047cc222c01b
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureFlick.h
@@ -0,0 +1,16 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOObject.h"
+
+@class MLOGestureEngine,UIPanGestureRecognizer;
+@interface MLOGestureFlick : MLOObject
+
+-(id)initWithEngine:(MLOGestureEngine *) engine;
+-(BOOL)eval:(UIPanGestureRecognizer *) pan;
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureFlick.m b/ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureFlick.m
new file mode 100644
index 000000000000..e3b3fd2a3ac2
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureFlick.m
@@ -0,0 +1,224 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOGestureFlick.h"
+#import "MLOGestureEngine_Impl.h"
+#import "MLOMainViewController.h"
+#import "MLOScrollerViewController.h"
+#import "MLORenderManager.h"
+#import "MLOAnimation.h"
+#import "mlo_utils.h"
+
+@interface MLOGestureFlick ()
+@property MLOGestureEngine * engine;
+@property CFTimeInterval startTime;
+@property CGPoint startPoint;
+@property CGFloat xFlickSpeed,yFlickSpeed;
+@property BOOL isEvaluatingFlic;
+@end
+
+static const CGFloat
+ MAX_SPEED = MLO_IPAD_HEIGHT_IN_PIXELS/0.5f, // max speed is the height per half a second
+ MAX_DURATION = 5.0f, // 5 seconds flic top
+ DECCELERATION = 800.0f,
+ SPEED_IGNORE_LIMIT=2.0f,
+ FLICK_FPS=50.0f;
+
+static const NSTimeInterval
+ MAX_INTERVAL_BETWEEN_EVENTS_THRESHOLD=0.7f; // 70% a second
+
+@implementation MLOGestureFlick
+
+-(CGFloat) normalizeSpeed:(CGFloat) gestureSpeed currentSpeed:(CGFloat) currentSpeed{
+ NSLog(@"GestureSpeed=%f currentSpeed=%f",gestureSpeed,currentSpeed);
+ if(currentSpeed* gestureSpeed > 0){
+ gestureSpeed+=currentSpeed;
+ }
+ if(gestureSpeed > MAX_SPEED){
+ return MAX_SPEED;
+ }
+ if (gestureSpeed < -MAX_SPEED){
+ return -MAX_SPEED;
+ }
+ if (abs(gestureSpeed) < SPEED_IGNORE_LIMIT) {
+ return 0;
+ }
+ return gestureSpeed;
+
+}
+-(id)initWithEngine:(MLOGestureEngine *) engine{
+
+ self = [self init];
+
+ if(self){
+ self.engine = engine;
+ _startTime = -1;
+ _yFlickSpeed= _xFlickSpeed=0.0f;
+ _isEvaluatingFlic =NO;
+ }
+ return self;
+}
+
+-(BOOL)eval:(UIGestureRecognizer *) gesture{
+
+ BOOL returned = NO;
+
+ UIGestureRecognizerState state = gesture.state;
+
+ if(state == UIGestureRecognizerStateBegan){
+ self.isEvaluatingFlic = YES;
+
+ self.startTime = CACurrentMediaTime();
+ self.startPoint = [gesture locationInView:_engine.renderer.view];
+
+ }else if(state == UIGestureRecognizerStateFailed
+ || state == UIGestureRecognizerStateCancelled){
+ self.startTime = -1;
+ self.isEvaluatingFlic =NO;
+
+ }else{
+
+ if(state == UIGestureRecognizerStateEnded){
+
+ CFTimeInterval startTime = self.startTime;
+
+ CGFloat xSpeed = self.xFlickSpeed;
+ CGFloat ySpeed = self.yFlickSpeed;
+
+ [_engine.currentAnimation cancel];
+
+ if(startTime > 0){
+
+ CGPoint t0 =self.startPoint;
+
+ CFTimeInterval deltaT = CACurrentMediaTime() - startTime;
+
+ self.startTime =-1;
+
+ if( (deltaT < MAX_INTERVAL_BETWEEN_EVENTS_THRESHOLD) &&
+ (deltaT > 0) &&
+ (_engine.handledGesturesCount == 0)){
+
+ CGPoint t1 = [gesture locationInView:_engine.renderer.view];
+
+
+ returned = [self flicXSpeed: [self normalizeSpeed: (t1.x - t0.x) / deltaT
+ currentSpeed: xSpeed]
+ ySpeed: [self normalizeSpeed: (t1.y - t0.y) / deltaT
+ currentSpeed: ySpeed]];
+ }
+ }
+
+ self.isEvaluatingFlic =NO;
+ }
+ }
+
+ return returned;
+
+}
+
+-(BOOL)flicXSpeed:(CGFloat) xSpeedInitial ySpeed:(CGFloat) ySpeedInitial{
+
+ if((xSpeedInitial !=0) || (ySpeedInitial!=0)) {
+
+ NSLog(@"FLIC: xSpeed=%f ySpeed=%f",xSpeedInitial, ySpeedInitial);
+
+ __block CGFloat xDistanceTotal = 0,yDistanceTotal=0;
+
+ const CGFloat maxSpeedVector = max( abs(xSpeedInitial) , abs(ySpeedInitial) );
+ const CGFloat duration =min( maxSpeedVector / DECCELERATION , MAX_DURATION );
+ const CGFloat deccelerationRate = maxSpeedVector / duration;
+ const CGFloat xSign= xSpeedInitial<0? -1: 1;
+ const CGFloat ySign= ySpeedInitial<0? -1: 1;
+
+ MLOScrollerViewController * scroller = _engine.scroller;
+
+ __block MLOAnimation * copy = nil;
+
+ MLOAnimation * animation =
+ [[MLOAnimation alloc]
+ initWithBehavior: CANCELABLE
+ fractionType: FULL_FRACTION
+ animation: ^(CGFloat fraction){
+
+ CGFloat time = fraction * duration;
+ CGFloat reducedSpeed = deccelerationRate* time;
+ CGFloat decelerationDistance = reducedSpeed *time / 2.0f;
+
+ CGFloat xDistanceCurrent = xSpeedInitial *time;
+ CGFloat yDistanceCurrent = ySpeedInitial *time;
+ CGFloat xSpeedCurrent = 0;
+ CGFloat ySpeedCurrent = 0;
+
+ if(xSign*xDistanceCurrent > decelerationDistance){
+ xDistanceCurrent -= (xSign * decelerationDistance);
+ xSpeedCurrent = xSpeedInitial - xSign * reducedSpeed;
+ }else{
+ xDistanceCurrent = xDistanceTotal;
+ }
+
+ if(ySign*yDistanceCurrent > decelerationDistance){
+ yDistanceCurrent -= (ySign * decelerationDistance);
+ ySpeedCurrent = ySpeedInitial - ySign * reducedSpeed;
+
+ }else{
+ yDistanceCurrent = yDistanceTotal;
+ }
+
+ [self setFlicSpeedX:xSpeedCurrent y:ySpeedCurrent context:@"FLIC iteration"];
+
+ CGFloat deltaX = xDistanceCurrent - xDistanceTotal;
+ CGFloat deltaY = yDistanceCurrent - yDistanceTotal;
+
+ if([_engine loPanDeltaX:deltaX deltaY:deltaY state:UIGestureRecognizerStateChanged]){
+
+ [scroller updateByPixelDeltaY:deltaY];
+
+ xDistanceTotal = xDistanceCurrent;
+ yDistanceTotal = yDistanceCurrent;
+ }else{
+ [copy cancel];
+ }
+ } ];
+
+ animation.duration = duration;
+ animation.fps = FLICK_FPS;
+ [animation linearCurve];
+
+ copy = animation;
+
+ animation.endBlock = ^{
+ if(![copy isCancelled] || !self.isEvaluatingFlic){
+
+ [self setFlicSpeedX:0.0f y:0.0f context:@"FLIC end"];
+ [_engine endFlick];
+ }
+ };
+ [_engine.currentAnimation cancel];
+ _engine.currentAnimation = animation;
+
+ [animation animate];
+
+ return YES;
+ }
+
+ NSLog(@"FLIC ignored: xSpeed = ySpeed = 0");
+
+ return NO;
+ }
+
+-(void) setFlicSpeedX: (CGFloat) xSpeed y:(CGFloat) ySpeed context:(NSString *)context{
+ self.xFlickSpeed = xSpeed;
+ self.yFlickSpeed = ySpeed;
+ if(LOG_FLICK_FRAMES){
+ NSLog(@"FLIC (%@) : set xSpeed = %f, ySpeed = %f",context, xSpeed,ySpeed);
+ }
+}
+
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureLimiter.h b/ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureLimiter.h
new file mode 100644
index 000000000000..3c351cda29f0
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureLimiter.h
@@ -0,0 +1,33 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOObject.h"
+
+static const CGFloat
+ MAX_ZOOM = 600.0f,
+ MIN_ZOOM = 80.0f;
+
+typedef enum {DELTA_X,DELTA_Y} MLOPixelDeltaDirection;
+#define MLOPixelDeltaDirectionString(enum) [@[@"DELTA_X",@"DELTA_Y"] objectAtIndex:enum]
+
+@class MLOGestureEngine;
+@interface MLOGestureLimiter : MLOObject
+@property CGSize documentSizeInLogic;
+
+-(id) initWithGestureEngine:(MLOGestureEngine *) engine;
+-(void) showLibreOffice;
+-(CGFloat)limitDelta:(CGFloat) delta direction:(MLOPixelDeltaDirection) direction;
+-(void)logPanRawDeltaX:(NSInteger) preDeltaX rawDeltaY:(NSInteger) preDeltaY limitedDeltaX:(NSInteger) actualDeltaX limitedDeltaY:(NSInteger) actualDeltaY;
+-(void)beginPinch;
+-(void)onRotate;
+-(CGFloat)inPinchGetRatioToLastScale:(CGFloat) newScale;
+-(void)fireLoZoomEventsDuringPinch;
+-(CGFloat)currentPinchScale;
+-(CGFloat)endPinchAndGetScaleForLo:(CGFloat)scale;
+-(CGFloat)zoom;
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureLimiter.m b/ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureLimiter.m
new file mode 100644
index 000000000000..9b94ad7feca3
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/gestures/MLOGestureLimiter.m
@@ -0,0 +1,269 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOGestureLimiter.h"
+#import "MLOGestureEngine_Impl.h"
+#import "MLOMainViewController_Impl.h"
+#import "MLOScrollerData.h"
+#import "MLOScrollerViewController.h"
+#import "MLORenderManager_Impl.h"
+#import "mlo_utils.h"
+#import "mlo_uno.h"
+
+@interface MLOGestureLimiter ()
+@property MLOGestureEngine * engine;
+@property MLOMainViewController * mainViewController;
+@property CGFloat actualZoom;
+@property CGFloat actualPixelToLogicScale;
+@property CGSize halfViewSizeInLogic;
+@property CGPoint viewCenterInLogic;
+@property BOOL didCreateViewCenterInLogic;
+@property CGFloat initialPinchZoom;
+@property CGFloat previousPinchScale;
+@property CGFloat previousScaleSentToLibreOffice;
+@end
+
+static const CGFloat DELTA_SCALE_ZOOM_IN_THRESHOLD=1.5f,
+ DELTA_SCALE_ZOOM_OUT_THRESHOLD=0.7f,
+ MIN_ZOOM_FOR_HORIZONAL_PAN = 133.0f;
+
+
+@implementation MLOGestureLimiter
+
+-(CGFloat) zoom{
+ return self.actualZoom;
+}
+-(id) initWithGestureEngine:(MLOGestureEngine *) engine{
+
+ self = [self init];
+ if(self){
+ self.engine= engine;
+ self.mainViewController = nil;
+ }
+ return self;
+}
+
+-(void) showLibreOffice{
+ self.mainViewController = _engine.mainViewController;
+ [self resetLocationMetrics];
+}
+
+-(NSString *)azimuthToString:(CGFloat) delta direction:(MLOPixelDeltaDirection) direction{
+ if(delta==0){
+ return @"N/A";
+ }
+ switch (direction) {
+ case DELTA_X:
+ if(delta < 0.0f) {
+ return @"swipe LEFT (scroll right)";
+ }
+ return @"swipe RIGHT (scroll left)";
+
+ case DELTA_Y:
+ if(delta < 0.0f){
+
+ return @"swipe UP (scroll down)";
+ }
+ return @"swipe DOWN (scroll up)";
+ }
+}
+
+-(void)logPanRawDeltaX:(NSInteger) rawDeltaX rawDeltaY:(NSInteger) rawDeltaY limitedDeltaX:(NSInteger) limitedDeltaX limitedDeltaY:(NSInteger) limitedDeltaY{
+ NSLog(@"PAN %@ %@: limited:(%d,%d) raw:(%d,%d) center:(%d,%d) viewSize:(%d,%d) logicSize:(%d,%d)",
+ [self azimuthToString:rawDeltaX direction:DELTA_X],
+ [self azimuthToString:rawDeltaY direction:DELTA_Y],
+ limitedDeltaX,
+ limitedDeltaY,
+ rawDeltaX,
+ rawDeltaY,
+ (NSInteger)self.viewCenterInLogic.x,
+ (NSInteger)self.viewCenterInLogic.y,
+ (NSInteger)self.halfViewSizeInLogic.width *2,
+ (NSInteger)self.halfViewSizeInLogic.height *2,
+ (NSInteger)self.documentSizeInLogic.width,
+ (NSInteger)self.documentSizeInLogic.height);
+}
+
+
+-(CGFloat)limitDelta:(CGFloat) delta direction:(MLOPixelDeltaDirection) direction{
+
+ if(delta==0){
+ return 0;
+ }
+ CGFloat deltaInLogic = [self pixelsToLogic:delta];
+
+ CGFloat limit = [self limitForRawDelta:deltaInLogic direction:direction];
+
+ if(deltaInLogic > 0){
+ deltaInLogic = min(limit,deltaInLogic);
+ }else{
+ deltaInLogic = max(limit,deltaInLogic);
+ }
+
+ [self updateCenterInLogic:deltaInLogic direction:direction];
+
+ return [self logicToPixels:deltaInLogic];
+}
+
+-(CGFloat) limitForRawDelta:(CGFloat) raw direction:(MLOPixelDeltaDirection) direction{
+
+ CGFloat halfscreen = [self halfViewSizeInLogic:direction];
+ CGFloat center = [self viewCenterCord:direction];
+
+ CGFloat limit;
+
+ if(raw < 0.0f){
+
+ CGFloat document = [self documentSizeInLogic:direction];
+ limit = halfscreen + center - document;
+
+ if(LOG_GESTURE_LIMITING){
+ NSLog(@"%@ LIMIT: raw=%f limit(%f) = halfscreen(%f) + center(%f) - document(%f)",MLOPixelDeltaDirectionString(direction),raw,limit,halfscreen,center,document);
+ }
+
+ }else{
+ limit = center - halfscreen;
+
+ if(LOG_GESTURE_LIMITING){
+ NSLog(@"%@ LIMIT: raw=%f limit(%f) = center(%f) - halfscreen(%f)",MLOPixelDeltaDirectionString(direction),raw,limit,center,halfscreen);
+ }
+ }
+ if(limit*raw <0){
+ // negative means limit flipped sign, so limit is zero
+ return 0;
+ }
+
+ return limit;
+}
+
+-(CGFloat) halfViewSizeInLogic:(MLOPixelDeltaDirection) direction{
+ switch (direction) {
+ case DELTA_X: return self.halfViewSizeInLogic.width;
+ case DELTA_Y: return self.halfViewSizeInLogic.height;
+ }
+}
+
+-(CGFloat) documentSizeInLogic:(MLOPixelDeltaDirection) direction{
+ switch (direction) {
+ case DELTA_X: return self.documentSizeInLogic.width;
+ case DELTA_Y: return self.documentSizeInLogic.height;
+ }
+}
+
+-(CGFloat) viewCenterCord:(MLOPixelDeltaDirection) direction{
+ switch (direction) {
+ case DELTA_X: return [self centerInLogic].x;
+ case DELTA_Y: return [self centerInLogic].y;
+ }
+}
+
+-(void) updateCenterInLogic:(CGFloat) delta direction:(MLOPixelDeltaDirection) direction{
+ switch (direction) {
+ case DELTA_X: _viewCenterInLogic.x-=delta; break;
+ case DELTA_Y: _viewCenterInLogic.y-=delta; break;
+ }
+}
+
+-(void)createHalfViewSizeInLogic{
+ self.halfViewSizeInLogic = CGSizeMake(_mainViewController.canvas.frame.size.width
+ * self.actualPixelToLogicScale
+ / 2.0f,
+ _mainViewController.canvas.frame.size.height
+ * self.actualPixelToLogicScale
+ / 2.0f);
+}
+
+-(CGFloat)pixelsToLogic:(CGFloat) distanceInPixels{
+ return roundf(self.actualPixelToLogicScale * distanceInPixels);
+}
+
+-(CGFloat)logicToPixels:(CGFloat) distanceInLogic{
+ return roundf(distanceInLogic / self.actualPixelToLogicScale);
+}
+
+-(CGPoint)centerInLogic{
+ if(!self.didCreateViewCenterInLogic){
+ [self createHalfViewSizeInLogic];
+ self.viewCenterInLogic = CGPointMake(self.halfViewSizeInLogic.width,
+ self.halfViewSizeInLogic.height);
+ self.didCreateViewCenterInLogic = YES;
+ }
+
+ return self.viewCenterInLogic;
+}
+
+-(void)resetLocationMetrics{
+ self.actualZoom = 100.0f;
+ [self updateActualZoom:100.f];
+ self.didCreateViewCenterInLogic = NO;
+}
+
+-(void)updateActualZoom:(CGFloat) newActualZoom{
+
+ CGFloat viewResizeScale = self.actualZoom / newActualZoom;
+
+ self.halfViewSizeInLogic = CGSizeMake(self.halfViewSizeInLogic.width * viewResizeScale,
+ self.halfViewSizeInLogic.height * viewResizeScale);
+ self.actualZoom = newActualZoom;
+
+ static const CGFloat PIXEL_TO_LOGIC_RATION_TIMES_HUNDRED = PIXEL_TO_LOGIC_RATIO * 100.0f;
+
+ self.actualPixelToLogicScale = PIXEL_TO_LOGIC_RATION_TIMES_HUNDRED / newActualZoom;
+ }
+
+-(void)beginPinch{
+ [_mainViewController.scroller updateByLogic];
+ self.previousPinchScale = NO_SCALE;
+ self.previousScaleSentToLibreOffice = NO_SCALE;
+ self.initialPinchZoom = self.actualZoom;
+}
+
+
+-(void)onRotate{
+ if(self.didCreateViewCenterInLogic){
+ [self createHalfViewSizeInLogic];
+ }
+}
+-(CGFloat) inPinchGetRatioToLastScale:(CGFloat)newScale{
+
+ CGFloat newZoom = self.initialPinchZoom *newScale;
+
+ newZoom = max(min(newZoom, MAX_ZOOM),MIN_ZOOM);
+
+ NSLog(@"new zoom is %f",newZoom);
+
+ [self updateActualZoom:newZoom];
+
+ newScale = newZoom / self.initialPinchZoom;
+
+ CGFloat scaleRatioToLastScale = newScale / self.previousPinchScale;
+
+ self.previousPinchScale =newScale;
+
+ return scaleRatioToLastScale;
+}
+
+-(void)fireLoZoomEventsDuringPinch{
+ CGFloat deltaScale = self.previousPinchScale / self.previousScaleSentToLibreOffice;
+
+ if((deltaScale > DELTA_SCALE_ZOOM_IN_THRESHOLD) ||
+ (deltaScale < DELTA_SCALE_ZOOM_OUT_THRESHOLD)){
+ self.previousScaleSentToLibreOffice = self.previousPinchScale;
+ [_engine loZoomDeltaX:0.0f deltaY:0.0f scale:deltaScale];
+ }
+}
+-(CGFloat)endPinchAndGetScaleForLo:(CGFloat)scale{
+ [self updateActualZoom: floorf(self.actualZoom)];
+ return scale/self.previousScaleSentToLibreOffice;
+}
+
+-(CGFloat)currentPinchScale{
+ return self.previousPinchScale;
+}
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/gestures/MLOKeyboardManager.h b/ios/shared/ios_sharedlo/objective_c/gestures/MLOKeyboardManager.h
new file mode 100644
index 000000000000..1437f3b33cef
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/gestures/MLOKeyboardManager.h
@@ -0,0 +1,18 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOObject.h"
+
+@class MLOMainViewController;
+@interface MLOKeyboardManager : MLOObject<UITextViewDelegate>
+
+-(id)initWithMainViewController:(MLOMainViewController *) mainViewController;
+-(void)addToMainViewController;
+-(void)show;
+-(void)hide;
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/gestures/MLOKeyboardManager.m b/ios/shared/ios_sharedlo/objective_c/gestures/MLOKeyboardManager.m
new file mode 100644
index 000000000000..05bf576dc531
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/gestures/MLOKeyboardManager.m
@@ -0,0 +1,111 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOKeyboardManager.h"
+#import "MLOMainViewController_Impl.h"
+#import "MLOManager.h"
+#import "MLOGestureEngine_Impl.h"
+#include <touch/touch.h>
+
+@interface MLOKeyboardManager ()
+@property MLOMainViewController * mainViewController;
+@property UITextView * textView;
+@property BOOL isShown;
+@end
+
+@implementation MLOKeyboardManager
+
+-(id)initWithMainViewController:(MLOMainViewController *) mainViewController{
+ self = [self init];
+ if(self){
+
+ self.mainViewController = mainViewController;
+
+ [self initTextView];
+
+ self.isShown = NO;
+
+ id defaultCenter = [NSNotificationCenter defaultCenter];
+
+ [defaultCenter addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
+ [defaultCenter addObserver:self selector:@selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];
+ }
+ return self;
+}
+-(void)addToMainViewController{
+ [self.mainViewController.canvas addSubview:self.textView];
+}
+-(void)initTextView{
+ self.textView = [[UITextView alloc] initWithFrame:CGRECT_ONE];
+ self.textView.alpha = 0.0f;
+ self.textView.autocapitalizationType = UITextAutocapitalizationTypeNone;
+ self.textView.delegate = self;
+}
+
+-(void)show{
+ self.isShown =YES;
+ NSLog(@"MLOKeyboardManager : show");
+ [self.textView becomeFirstResponder];
+}
+
+-(void)hide{
+ if(self.isShown){
+ self.isShown =NO;
+ NSLog(@"MLOKeyboardManager : hide");
+ [self.textView resignFirstResponder];
+ }
+}
+
+-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
+{
+ NSLog(@"textView: %@ shouldChangeTextInRange:[%u,%u] replacementText:%@", textView, range.location, range.length, text);
+
+ for (NSUInteger i = 0; i < [text length]; i++){
+ touch_lo_keyboard_input([text characterAtIndex: i]);
+ }
+ return NO;
+}
+
+
+-(BOOL)canBecomeFirstResponder{
+ return YES;
+}
+
+-(void)keyboardWillShow:(NSNotification *)note{
+ IGNORE_ARG(note);
+ [self.mainViewController.gestureEngine onKeyboardShow];
+}
+
+-(void)keyboardDidHide:(NSNotification *)note{
+ IGNORE_ARG(note);
+ [self.mainViewController.gestureEngine onKeyboardHide];
+}
+
+
+// C functions
+// ===========
+//
+// Functions called in the LO thread, which thus need to dispatch any
+// CocoaTouch activity to happen on the GUI thread. Use
+// dispatch_async() consistently.
+
+void touch_ui_show_keyboard()
+{
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [[MLOManager getInstance].mainViewController.keyboard show];
+ });
+}
+
+void touch_ui_hide_keyboard()
+{
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [[MLOManager getInstance].mainViewController.keyboard hide];
+ });
+}
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/render/MLOPostRenderManager.h b/ios/shared/ios_sharedlo/objective_c/render/MLOPostRenderManager.h
new file mode 100644
index 000000000000..10323974b0a2
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/render/MLOPostRenderManager.h
@@ -0,0 +1,13 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOObject.h"
+
+@interface MLOPostRenderManager : MLOObject
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/render/MLOPostRenderManager.m b/ios/shared/ios_sharedlo/objective_c/render/MLOPostRenderManager.m
new file mode 100644
index 000000000000..06c5d3f6e34f
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/render/MLOPostRenderManager.m
@@ -0,0 +1,34 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOPostRenderManager.h"
+#import "MLOMainViewController.h"
+
+@interface MLOPostRenderManager ()
+@property UITextView * invisibleSelection;
+@end
+
+@implementation MLOPostRenderManager
+
+-(id)init{
+ self = [super init];
+ if(self){
+ self.invisibleSelection = [UITextView new];
+
+ _invisibleSelection.backgroundColor = [UIColor clearColor];
+ _invisibleSelection.textColor = [UIColor clearColor];
+
+ }
+ return self;
+}
+
+-(void)addToMainViewController:(MLOMainViewController *) mainViewController{
+ [mainViewController.canvas addSubview:_invisibleSelection];
+}
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/render/MLORenderBuffer.h b/ios/shared/ios_sharedlo/objective_c/render/MLORenderBuffer.h
new file mode 100644
index 000000000000..b02ff957c1d0
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/render/MLORenderBuffer.h
@@ -0,0 +1,19 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLORenderingUIView.h"
+
+@class MLORenderManager;
+@interface MLORenderBuffer : MLORenderingUIView
+@property NSInteger index;
+@property MLORenderBuffer * previous;
+-(id)initWithArrayIndex:(NSInteger) index renderManager:(MLORenderManager *) manager;
++(CGFloat) getAverageFps;
++(CGFloat) getMaxFps;
+-(void)hide;
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/render/MLORenderBuffer.m b/ios/shared/ios_sharedlo/objective_c/render/MLORenderBuffer.m
new file mode 100644
index 000000000000..a06f91d8fecb
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/render/MLORenderBuffer.m
@@ -0,0 +1,106 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLORenderBuffer.h"
+#import "MLORenderManager_Impl.h"
+#import "mlo_utils.h"
+#import <QuartzCore/QuartzCore.h>
+#include <touch/touch.h>
+
+@interface MLORenderBuffer ()
+@property MLORenderManager * manager;
+@end
+static const CGFloat
+ MIN_AVERAGE_RENDER_TIME_THRESHOLD=1.0f/100.0f,
+ MIN_FPS=10.0f;
+
+static const NSTimeInterval SCALING_ANIMATION_DURATION = 0.02f;
+
+static CGFloat averageFps,maxFps;
+@implementation MLORenderBuffer
+
+-(id)initWithArrayIndex:(NSInteger) index renderManager:(MLORenderManager *) manager{
+ self= [self init];
+ if(self){
+ self.index = index;
+ self.manager = manager;
+ self.backgroundColor = [UIColor whiteColor];
+ self.previous = nil;
+ }
+ return self;
+}
+
+-(void)hide{
+ self.alpha = 0;
+ [self resetTransform];
+}
+
+-(void)setNeedsDisplayInRect:(CGRect)rect{
+ [self resetTransform];
+ [super setNeedsDisplayInRect:rect];
+}
+
+-(void) resetTransform{
+ if(self.frame.origin.x ||self.frame.origin.y ){
+ self.frame = CGRectMake(0,0,_manager.bufferFrame.size.width,_manager.bufferFrame.size.height);
+ }
+}
+
+- (void)drawRect:(CGRect)rect
+{
+
+ CGContextRef context = UIGraphicsGetCurrentContext();
+
+ //rect = self.frame;
+ LOG_RECT(rect, @"drawRect");
+
+ CGContextSaveGState(context);
+ CGContextSetFillColorWithColor(context,[UIColor whiteColor].CGColor);
+ CGContextTranslateCTM(context, 0, _manager.bufferFrame.size.height);
+ CGContextScaleCTM(context, 1, -1);
+ CGContextScaleCTM(context, 1, 1);
+ NSDate *startDate = [NSDate date];
+
+ [_manager loRenderWillBegin];
+
+ touch_lo_render_windows(context, rect.origin.y, rect.origin.y, rect.size.width, rect.size.height);
+
+ CGContextRestoreGState(context);
+
+ CGFloat duration = [[NSDate date] timeIntervalSinceDate: startDate];
+
+ maxFps = max(maxFps,1.0f/duration);
+
+ static float totalTime = 0,counter = 0;
+
+ totalTime +=duration;
+ counter++;
+
+ CGFloat averageTime = totalTime / counter;
+ if(averageTime >MIN_AVERAGE_RENDER_TIME_THRESHOLD){
+ averageFps = 1.0f/ averageTime;
+ }
+
+ if(LOG_DRAW_RECT){
+ NSLog(@"drawRect: lo_render_windows: time=%f sec, average=%f sec, fps=%f",
+ duration, averageTime, averageFps);
+ }
+ if(_manager.currentGesture != PINCH){
+ [_manager swapPreviousBuffer:_previous withNextBuffer:self];
+ }
+}
+
++(CGFloat) getAverageFps{
+ return max(averageFps, MIN_FPS);
+}
+
++(CGFloat) getMaxFps{
+ return max(maxFps, MIN_FPS);
+}
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/render/MLORenderManager.h b/ios/shared/ios_sharedlo/objective_c/render/MLORenderManager.h
new file mode 100644
index 000000000000..75eb67ef6838
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/render/MLORenderManager.h
@@ -0,0 +1,30 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOViewController.h"
+#import <UIKit/UIKit.h>
+
+static const BOOL ENABLE_PINCH_RENDERING_VIA_IOS = YES;
+
+@class MLOGestureEngine;
+
+@interface MLORenderManager : MLOViewController
+
++(MLORenderManager *) getInstance;
+
+-(void) showLibreOffice:(MLOGestureEngine *) gestureEngine;
+-(void) hideLibreOffice;
+-(void) panDeltaX:(CGFloat) deltaX deltaY:(CGFloat) deltaY;
+-(void) pinchDeltaX:(CGFloat)deltaX deltaY:(CGFloat)deltaY scale:(CGFloat)scale;
+-(void) endGestures;
+-(void)setWidth:(NSInteger) width height:(NSInteger) height;
+-(void) renderInContext:(CGContextRef) context;
+-(CGPoint) getShiftFromCanvasCenter;
+-(void)renderNow;
+@end
+
diff --git a/ios/shared/ios_sharedlo/objective_c/render/MLORenderManager.m b/ios/shared/ios_sharedlo/objective_c/render/MLORenderManager.m
new file mode 100644
index 000000000000..3f9818e8e2cd
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/render/MLORenderManager.m
@@ -0,0 +1,332 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOCommon.h"
+
+#import <UIKit/UIKit.h>
+
+#import "MLOMainViewController.h"
+#import "MLORenderManager_Impl.h"
+#import "MLORenderBuffer.h"
+#import "MLOScalingBuffer.h"
+#import "MLOGestureLimiter.h"
+#import "MLOGestureEngine_Impl.h"
+#import "MLOSelectionViewController.h"
+#import "NSObject+MLOUtils.h"
+#import "MLOPostRenderManager.h"
+#import "mlo_utils.h"
+#import <QuartzCore/QuartzCore.h>
+
+#include <touch/touch.h>
+
+static MLORenderManager * instance = nil;
+
+static const CGFloat
+ HORIZONAL_BUFFER_SCALE=1.0f,
+ VERTICAL_BUFFER_SCALE=1.0f,
+ BUFFER_SCALE_BIAS =1.0f,
+
+ RENDERING_BIAS_RATIO = 1.0f/(BUFFER_SCALE_BIAS*HORIZONAL_BUFFER_SCALE *VERTICAL_BUFFER_SCALE),
+
+ MAX_RENDER_PER_SECOND_ON_DEFAULT_ZOOM =4 * RENDERING_BIAS_RATIO,
+ MAX_RENDER_PER_SECOND_ON_MAX_ZOOM_IN=3 * RENDERING_BIAS_RATIO;
+
+static const NSTimeInterval
+ LO_PAN_RENDER_MAX_DURATION = 0.3f,
+ LO_PINCH_RENDER_MAX_DURATION = 0.5f,
+ RESET_TRANSFORM_ANIMATION_DURATION=0.1f,
+ LO_RENDER_BACKOFF_MIN = 1.0f / MAX_RENDER_PER_SECOND_ON_DEFAULT_ZOOM,
+ LO_RENDER_BACKOFF_MAX = 1.0f / MAX_RENDER_PER_SECOND_ON_MAX_ZOOM_IN,
+ LO_RENDER_BACK_OFF_MAX_DELTA = LO_RENDER_BACKOFF_MAX - LO_RENDER_BACKOFF_MIN;
+
+
+
+static const NSInteger BUFFER_COUNT=2;
+
+typedef enum {X,Y,Z} MLOGestureDirection;
+#define MLOGestureDirectionString(enum) [@[@"X",@"Y",@"Z"] objectAtIndex:enum]
+
+@interface MLORenderManager ()
+@property MLOGestureEngine * gestureEngine;
+@property MLOPostRenderManager * post;
+@property NSArray * buffers;
+@property NSInteger activeBufferIndex,nextBufferIndex,frameIdCounter;
+@property NSTimeInterval bufferTransfromResetDeadline,renderBlockReleaseTime;
+@property CGFloat inRenderTiltX,inRenderTiltY, inRenderTiltScale;
+@end
+
+@implementation MLORenderManager
+
++(MLORenderManager *) getInstance{
+ if(instance == nil){
+ instance = [MLORenderManager new];
+ }
+ return instance;
+}
+
+-(MLORenderBuffer *)getBufferAtIndex:(NSInteger) index{
+ return [_buffers objectAtIndex:index];
+}
+
+-(id)init{
+ self = [super init];
+ if(self){
+ self.gestureEngine = nil;
+ [self createBufffers];
+ self.renderBlockReleaseTime = 0;
+ self.activeBufferIndex = 0;
+ self.nextBufferIndex = _activeBufferIndex + 1;
+ [self loRenderWillBegin];
+ self.view.backgroundColor = [UIColor whiteColor];
+ self.currentGesture = NO_GESTURE;
+ }
+ return self;
+}
+
+-(void) createBufffers{
+ NSMutableArray * array = [NSMutableArray new];
+
+ for (NSInteger i = 0 ; i < BUFFER_COUNT; i++) {
+
+ [array addObject:[[MLORenderBuffer alloc] initWithArrayIndex: i renderManager:self]];
+ }
+
+ self.buffers = [NSArray arrayWithArray:array];
+
+ for (NSInteger i = 0 ; i < BUFFER_COUNT; i++) {
+
+ MLORenderBuffer * buffer = [_buffers objectAtIndex:i];
+
+ NSInteger previousIndex = BUFFER_COUNT -1;
+ if(i !=0){
+ previousIndex = i-1;
+ }
+ buffer.previous = [_buffers objectAtIndex:previousIndex];
+ [self.view addSubview:buffer];
+ }
+}
+
+-(void)showLibreOffice:(MLOGestureEngine *) gestureEngine{
+ self.gestureEngine = gestureEngine;
+}
+
+-(void)hideLibreOffice{
+ self.currentGesture = NO_GESTURE;
+ [self.scaler hide];
+ self.gestureEngine = nil;
+}
+
+-(void) panDeltaX:(CGFloat) deltaX deltaY:(CGFloat) deltaY{
+
+ self.currentGesture = PAN;
+
+ if(deltaX || deltaY){
+ [[self getActiveBuffer] moveDeltaX:deltaX deltaY:deltaY];
+
+ self.inRenderTiltX+=deltaX;
+ self.inRenderTiltY+=deltaY;
+ }
+}
+
+-(void) pinchDeltaX:(CGFloat)deltaX deltaY:(CGFloat)deltaY scale:(CGFloat)scale{
+
+ if(ENABLE_PINCH_RENDERING_VIA_IOS){
+
+ self.currentGesture = PINCH;
+
+ if(self.scaler ==nil){
+ self.scaler = [[MLOScalingBuffer alloc] initWithRenderManager:self];
+ }
+
+ [self.scaler scale:scale deltaX:deltaX deltaY:deltaY];
+
+ self.inRenderTiltScale*=scale;
+ self.inRenderTiltX = self.inRenderTiltX*scale +deltaX;
+ self.inRenderTiltY = self.inRenderTiltY*scale +deltaY;
+
+ }
+
+}
+-(void)endGestures{
+ self.currentGesture = NO_GESTURE;
+ NSLog(@"RenderManager: self.currentGesture = NO_GESTURE");
+}
+
+-(CGPoint) getShiftFromCanvasCenter{
+
+ CGPoint bufferCenter= [self currentBufferCenter];
+ CGPoint canvasCenter = _gestureEngine.mainViewController.canvas.center;
+
+ return CGPointMake(bufferCenter.x - canvasCenter.x,
+ bufferCenter.y - canvasCenter.y);
+}
+
+-(CGPoint) currentBufferCenter{
+ if(self.currentGesture ==PINCH){
+ return self.scaler.center;
+ }
+ return [self getActiveBuffer].center;
+}
+
+-(void)loRenderWillBegin{
+ self.inRenderTiltX = NO_MOVE_DELTA;
+ self.inRenderTiltY = NO_MOVE_DELTA;
+ self.inRenderTiltScale = NO_SCALE;
+}
+
+-(void)setWidth:(NSInteger) width height:(NSInteger) height{
+
+ self.view.frame = CGRectMake(0,0, width,height);
+
+ CGFloat bufferWidth = width*HORIZONAL_BUFFER_SCALE;
+ CGFloat bufferHeight = height*VERTICAL_BUFFER_SCALE;
+ self.bufferFrame = CGRectMake(0,0, bufferWidth,bufferHeight);
+
+ for (MLORenderBuffer * buffer in _buffers) {
+ buffer.frame = self.bufferFrame;
+ }
+
+ touch_lo_set_view_size(bufferWidth,bufferHeight);
+}
+-(MLORenderBuffer *) getActiveBuffer{
+ return[_buffers objectAtIndex:self.activeBufferIndex];
+}
+
+-(MLORenderBuffer *) getNextBuffer{
+ return[_buffers objectAtIndex:self.nextBufferIndex];
+}
+
+-(void) renderInContext:(CGContextRef) context{
+ // used for magnification
+ [[self getActiveBuffer].layer renderInContext:context];
+}
+
+-(void)swapIndexes{
+ self.nextBufferIndex = (self.nextBufferIndex +1)% BUFFER_COUNT;
+ self.activeBufferIndex = (self.activeBufferIndex +1)% BUFFER_COUNT;
+}
+
+-(void)swapPreviousBuffer:(MLORenderingUIView*) previous withNextBuffer:(MLORenderBuffer *) next{
+
+ NSTimeInterval bufferTransformResetDelay = [self getBufferTransformResetDelay];
+ NSTimeInterval bufferTransformResetDeadline =CACurrentMediaTime() + bufferTransformResetDelay;
+
+ self.bufferTransfromResetDeadline = bufferTransformResetDeadline;
+
+ if(self.scaler && self.scaler.didRender){
+ previous = self.scaler;
+ }
+
+ [self showBuffer:next];
+
+ [self swapIndexes];
+
+ [previous hide];
+
+}
+
+-(NSTimeInterval) getBufferTransformResetDelay{
+
+ switch(self.currentGesture){
+ case PAN: return LO_PAN_RENDER_MAX_DURATION;
+ case PINCH: return LO_PINCH_RENDER_MAX_DURATION;
+ case NO_GESTURE: return 0;
+ }
+}
+
+-(void)showBuffer:(MLORenderBuffer *) buffer{
+
+ buffer.alpha = 1.0f;
+}
+
+-(CGFloat) currentZoomRatio{
+ return [_gestureEngine.limiter zoom] / MAX_ZOOM;
+}
+
+-(void) renderWithRect:(CGRect) rect{
+
+ switch(self.currentGesture){
+ case PAN:
+ {
+ NSTimeInterval now = CACurrentMediaTime();
+
+ NSTimeInterval delta = LO_RENDER_BACKOFF_MIN +
+ LO_RENDER_BACK_OFF_MAX_DELTA * [self currentZoomRatio];
+
+ NSTimeInterval releaseTime = now + delta;
+
+ NSTimeInterval currentReleaseTime = self.renderBlockReleaseTime;
+
+ NSInteger currentFrameId = self.frameIdCounter++;
+
+ if(now > currentReleaseTime){
+
+ [self pereodicRender:rect releaseTime:releaseTime];
+
+ }else{
+
+ [self performBlock:^{
+
+ if((self.renderBlockReleaseTime == currentReleaseTime)
+ && (currentFrameId==0)){
+
+ [self pereodicRender:rect releaseTime:releaseTime];
+ }
+ }afterDelay:delta];
+ }
+ }
+ break;
+ case PINCH:
+ case NO_GESTURE:
+ [[self getNextBuffer] setNeedsDisplayInRect:rect];
+ break;
+ }
+ }
+
+-(void)renderNow{
+ [[self getNextBuffer] setNeedsDisplayInRect:self.bufferFrame];
+}
+
+-(void)pereodicRender:(CGRect) rect releaseTime:(NSTimeInterval) releaseTime{
+
+ static NSTimeInterval lastRender = 0;
+
+ [[self getNextBuffer] setNeedsDisplayInRect:rect];
+
+ self.frameIdCounter = 0;
+
+ self.renderBlockReleaseTime =releaseTime;
+
+ NSTimeInterval now = CACurrentMediaTime();
+ NSLog(@"Render interval %f",now - lastRender);
+
+ lastRender = now;
+}
+
+
+// C functions
+// ===========
+//
+// Functions called in the LO thread, which thus need to dispatch any
+// CocoaTouch activity to happen on the GUI thread. Use
+// dispatch_async() consistently.
+
+
+void touch_ui_damaged(CGRect rect)
+{
+ dispatch_async(dispatch_get_main_queue(), ^{
+
+ [[MLORenderManager getInstance] renderWithRect:rect];
+
+ });
+ // NSLog(@"lo_damaged: %dx%d@(%d,%d)", (int)rect.size.width, (int)rect.size.height, (int)rect.origin.x, (int)rect.origin.y);
+}
+
+@end
+
+// vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/ios/shared/ios_sharedlo/objective_c/render/MLORenderManager_Impl.h b/ios/shared/ios_sharedlo/objective_c/render/MLORenderManager_Impl.h
new file mode 100644
index 000000000000..b7f3350f68df
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/render/MLORenderManager_Impl.h
@@ -0,0 +1,26 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLORenderManager.h"
+
+static const CGFloat
+ NO_SCALE = 1.0f,
+ NO_MOVE_DELTA = 0.0f;
+
+typedef enum {PAN,PINCH,NO_GESTURE} MLOGestureType;
+#define MLOGestureTypeString(enum) [@[@"PAN",@"PINCH",@"NO_GESTURE"] objectAtIndex:enum]
+
+@class MLORenderBuffer,MLOScalingBuffer;
+@interface MLORenderManager ()
+@property MLOScalingBuffer * scaler;
+@property CGRect bufferFrame;
+@property MLOGestureType currentGesture;
+-(void)swapPreviousBuffer:(MLORenderBuffer*) previous withNextBuffer:(MLORenderBuffer *) next;
+-(void)loRenderWillBegin;
+-(MLORenderBuffer *) getActiveBuffer;
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/render/MLORenderingUIView.h b/ios/shared/ios_sharedlo/objective_c/render/MLORenderingUIView.h
new file mode 100644
index 000000000000..91df87556594
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/render/MLORenderingUIView.h
@@ -0,0 +1,16 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOSubView.h"
+
+@interface MLORenderingUIView: MLOSubView
+
+-(void)moveDeltaX:(CGFloat) deltaX deltaY:(CGFloat) deltaY;
+-(void)hide;
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/render/MLORenderingUIView.m b/ios/shared/ios_sharedlo/objective_c/render/MLORenderingUIView.m
new file mode 100644
index 000000000000..5a3436f18d0f
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/render/MLORenderingUIView.m
@@ -0,0 +1,20 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLORenderingUIView.h"
+
+@implementation MLORenderingUIView
+
+-(void)moveDeltaX:(CGFloat) deltaX deltaY:(CGFloat) deltaY{
+ CGPoint center = self.center;
+ self.center = CGPointMake(center.x+ deltaX,center.y + deltaY);
+}
+-(void)hide{
+ NSLog(@"Unimplemnted hide method for %@",self);
+}
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/render/MLOScalingBuffer.h b/ios/shared/ios_sharedlo/objective_c/render/MLOScalingBuffer.h
new file mode 100644
index 000000000000..6ffec4c5e78a
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/render/MLOScalingBuffer.h
@@ -0,0 +1,16 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLORenderingUIView.h"
+
+@class MLORenderManager;
+@interface MLOScalingBuffer :MLORenderingUIView
+@property BOOL didRender;
+-(id)initWithRenderManager:(MLORenderManager *) manager;
+-(void)scale:(CGFloat) scale deltaX:(CGFloat) deltaX deltaY:(CGFloat) deltaY;
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/render/MLOScalingBuffer.m b/ios/shared/ios_sharedlo/objective_c/render/MLOScalingBuffer.m
new file mode 100644
index 000000000000..01d369504632
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/render/MLOScalingBuffer.m
@@ -0,0 +1,79 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOScalingBuffer.h"
+#import "MLORenderBuffer.h"
+#import "MLORenderingUIView.h"
+
+#import "MLORenderManager_Impl.h"
+#import <QuartzCore/QuartzCore.h>
+
+@interface MLOScalingBuffer ()
+@property MLORenderManager * manager;
+@property MLORenderBuffer * active;
+@property BOOL didHideActive;
+@end
+
+@implementation MLOScalingBuffer
+
+-(id)initWithRenderManager:(MLORenderManager *) manager{
+ self= [self initWithFrame:manager.view.frame];
+ if(self){
+ self.didRender = NO;
+ self.didHideActive =NO;
+ self.manager = manager;
+ self.active =[manager getActiveBuffer];
+ self.alpha = 1.0f;
+ self.backgroundColor = [UIColor clearColor];
+ [self.manager.view addSubview:self];
+ self.frame = manager.bufferFrame;
+ [self setNeedsDisplay];
+
+ }
+ return self;
+}
+
+-(void)hideActive{
+ if(self.didRender && !self.didHideActive){
+ self.didHideActive = YES;
+ [self.active hide];
+ }
+}
+
+-(void)scale:(CGFloat) scale deltaX:(CGFloat) deltaX deltaY:(CGFloat) deltaY{
+
+ [self hideActive];
+ if(self.didHideActive){
+ self.layer.transform = CATransform3DMakeScale(scale,scale,1);
+ }
+
+ [self moveDeltaX:deltaX deltaY:deltaY];
+}
+
+-(void)hide{
+ self.alpha = 0.0f;
+ [self removeFromSuperview];
+ self.manager.scaler = nil;
+}
+
+-(void)drawRect:(CGRect)rect{
+
+ if(!self.didRender){
+
+ CGContextRef context = UIGraphicsGetCurrentContext();
+// CGContextSaveGState(context);
+// CGContextFillRect(context, self.bounds);
+ [self.active.layer renderInContext:context];
+// CGContextRestoreGState(context);
+ self.didRender = YES;
+ }else{
+ [self hideActive];
+ [super drawRect:rect];
+ }
+}
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/utils/MLOAnimation.h b/ios/shared/ios_sharedlo/objective_c/utils/MLOAnimation.h
new file mode 100644
index 000000000000..f4f124d450d3
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/utils/MLOAnimation.h
@@ -0,0 +1,36 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOObject.h"
+
+typedef void (^MLOAnimationBlock)(CGFloat fraction);
+typedef void (^MLOAnimationBlockEnd)();
+
+typedef enum {CANCELABLE, MANDATORY} MLOAnimationBehavior;
+#define MLOAnimationBehaviorString(enum) [@[@"CANCELABLE",@"MANDATORY"] objectAtIndex:enum]
+typedef enum {DELTA_ONLY,FULL_FRACTION} MLOAnimationFractionType;
+#define MLOAnimationFractionTypeString(enum) [@[@"DELTA_ONLY",@"FULL_FRACTION"] objectAtIndex:enum]
+
+static const NSTimeInterval DEFAULT_MLO_ANIMATION_DURAION=1.0F;
+
+static const CGFloat DEFAULT_ANIMATION_FPS=25;
+
+@interface MLOAnimation : MLOObject
+@property NSTimeInterval duration;
+@property CGFloat fps;
+@property (nonatomic,strong) MLOAnimationBlockEnd endBlock;
+
+-(id)initWithBehavior:(BOOL) behavior fractionType:(MLOAnimationFractionType) fractionType animation:(MLOAnimationBlock) animation;
+-(void) linearCurve;
+-(void) easeOutCurve;
+-(void) easeInCurve;
+-(void) cancel;
+-(void) animate;
+-(BOOL) isCancelled;
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/utils/MLOAnimation.m b/ios/shared/ios_sharedlo/objective_c/utils/MLOAnimation.m
new file mode 100644
index 000000000000..ef6e030b9825
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/utils/MLOAnimation.m
@@ -0,0 +1,149 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOAnimation.h"
+
+
+typedef CGFloat (^MLOAnimationCurve)(CGFloat time);
+
+@interface MLOAnimation ()
+@property BOOL active,didPost,cancelled;
+@property CGFloat frameCount;
+@property NSDate * startDate;
+@property MLOAnimationBehavior behavior;
+@property MLOAnimationFractionType fractionType;
+@property (nonatomic,strong) MLOAnimationBlock animation;
+@property (nonatomic,strong) MLOAnimationCurve curve;
+@end
+
+@implementation MLOAnimation
+
+-(void) linearCurve{
+ static const MLOAnimationCurve LINEAR = ^(CGFloat completedFraction){
+ return completedFraction;
+ };
+ [self setCurve:LINEAR name:@"LINEAR"];
+}
+-(void) easeOutCurve{
+ static const MLOAnimationCurve EASE_OUT = ^(CGFloat completedFraction){
+ return 1 - completedFraction*completedFraction;
+ };
+ [self setCurve:EASE_OUT name:@"EASE_OUT"];
+}
+
+-(void) easeInCurve{
+ static const MLOAnimationCurve EASE_IN = ^(CGFloat completedFraction){
+ return completedFraction*completedFraction;
+ };
+
+ [self setCurve:EASE_IN name:@"EASE_IN"];
+}
+
+-(void)setCurve:(MLOAnimationCurve) curve name:(NSString *) name{
+ self.curve = curve;
+ NSLog(@"MLOAnimation curve set to: %@",name);
+}
+
+-(void) cancel{
+ if(_behavior == CANCELABLE){
+ self.cancelled= YES;
+ self.active = NO;
+ [self doPost:nil];
+
+ if(_startDate){
+
+ NSLog(@"MLOAnimation cancelled after %f millis",[_startDate timeIntervalSinceNow]);
+ }else{
+ NSLog(@"MLOAnimation aborted");
+ }
+ }else{
+ NSLog(@"CLOAnimation cannot be cancelled");
+ }
+}
+-(BOOL) isCancelled{
+ return self.cancelled;
+}
+
+-(id)initWithBehavior:(BOOL) behavior fractionType:(MLOAnimationFractionType) fractionType animation:(MLOAnimationBlock) animation{
+ self = [super init];
+ if(self){
+ _active=YES;
+ _duration = DEFAULT_MLO_ANIMATION_DURAION;
+ _fps = DEFAULT_ANIMATION_FPS;
+ _behavior=CANCELABLE;
+ _fractionType = fractionType;
+ _frameCount = -1.0f;
+ _startDate = nil;
+ _didPost =NO;
+ _cancelled=NO;
+ [self linearCurve];
+ self.animation = animation;
+ }
+ return self;
+}
+
+-(void)animate{
+
+ if(!_startDate){
+ self.startDate = [NSDate date];
+ _frameCount = _duration *_fps;
+
+ if(_frameCount>0){
+ CGFloat frameDuration = 1.0f/_fps;
+
+ NSLog(@"MLOAnimation: duration=%f frameCount=%f fps=%f frameDuration=%f fractionType=%@",_duration,_frameCount,_fps,frameDuration,[self fractionTypeAsString]);
+
+ for (CGFloat i = 1; i <= _frameCount; i++) {
+ [self performSelector:@selector(doFrame:) withObject:[NSNumber numberWithFloat:i] afterDelay: i*frameDuration];
+ }
+ [self performSelector:@selector(doPost:) withObject:nil afterDelay:_duration + frameDuration];
+ }else{
+ NSLog(@"MLOAnimation cannot run (zero frames)");
+ }
+ }
+}
+
+-(void) doPost:(NSObject *) niller{
+ if(!_didPost){
+ _didPost = YES;
+ if(_endBlock){
+ _endBlock();
+ }
+ }
+}
+
+-(NSString *)fractionTypeAsString{
+ switch (_fractionType) {
+ case DELTA_ONLY:
+ return @"DELTA_ONLY";
+ case FULL_FRACTION:
+ return @"FULL_FRACTION";
+ }
+}
+
+-(void)doFrame:(NSNumber *) frame{
+ if(_active){
+
+ CGFloat fFrame = [frame floatValue];
+
+ CGFloat currentFraction = _curve(fFrame/_frameCount);
+
+ if(_fractionType == DELTA_ONLY){
+ currentFraction -= _curve( (fFrame-1.0f) /_frameCount);
+ }
+
+ _animation(_curve(currentFraction));
+
+ if(fFrame ==_frameCount){
+
+ _behavior =MANDATORY;
+ }
+ }
+}
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/utils/MLOButton.h b/ios/shared/ios_sharedlo/objective_c/utils/MLOButton.h
new file mode 100644
index 000000000000..84821713460f
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/utils/MLOButton.h
@@ -0,0 +1,19 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOCommon.h"
+#import <UIKit/UIKit.h>
+@class MLOResourceImage;
+@interface MLOButton : UIButton
+
++(id)buttonWithImage:(MLOResourceImage *) image;
+-(void)addTarget:(id)target action:(SEL)action;
+-(void)addAction:(SEL)action;
+-(void)setDefaultImage:(UIImage *)image;
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/utils/MLOButton.m b/ios/shared/ios_sharedlo/objective_c/utils/MLOButton.m
new file mode 100644
index 000000000000..9d7bc974c153
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/utils/MLOButton.m
@@ -0,0 +1,35 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOButton.h"
+#import "MLOResourceImage.h"
+
+@implementation MLOButton
+
++(id)buttonWithImage:(MLOResourceImage *) image{
+ id button = [MLOButton buttonWithType:UIButtonTypeCustom];
+ if(button){
+ [button setDefaultImage:image.image];
+ }
+ return button;
+}
+
+
+-(void)addTarget:(id)target action:(SEL)action{
+ [self addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
+}
+-(void)addAction:(SEL)action{
+ [self addTarget:self action:action];
+}
+
+-(void)setDefaultImage:(UIImage *)image{
+ [self setImage:image forState:UIControlStateNormal];
+ self.contentMode = UIViewContentModeScaleAspectFit;
+}
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/utils/MLOCommon.h b/ios/shared/ios_sharedlo/objective_c/utils/MLOCommon.h
new file mode 100644
index 000000000000..fb14eabc1a5e
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/utils/MLOCommon.h
@@ -0,0 +1,59 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef __Mobile_LibreOffice_MLOCommon_h__
+#define __Mobile_LibreOffice_MLOCommon_h__
+
+static const BOOL
+ LOG_DRAW_RECT = NO,
+ LOG_GET_VIEW_DATA = YES,
+ LOG_FLICK_FRAMES=NO,
+ LOG_PAN=NO,
+ LOG_PINCH=YES,
+ LOG_DOUBLE_TAP=YES,
+ LOG_GESTURE_LIMITING = NO;
+
+#define LOG_RECT(RECT,NAME) NSLog(@"%@: w:%d, h:%d, origin:(%d,%d)",NAME, (int) RECT.size.width, (int) RECT.size.height, (int) RECT.origin.x, (int) RECT.origin.y)
+#define IGNORE_ARG(X) ((void) X)
+
+#define ARM
+#define ARM32
+#define BOOST_DETAIL_NO_CONTAINER_FWD
+#define CPPU_ENV gcc3
+#define DBG_UTIL
+#define DISABLE_DYNLOADING
+#define DISABLE_SCRIPTING
+#define ENABLE_READONLY_INSTALLSET
+#define IOS
+#define LIBO_INTERNAL_ONLY
+#define NO_PTHREAD_PRIORITY
+#define OSL_DEBUG_LEVEL 1
+#define SAL_LOG_INFO
+#define SAL_LOG_WARN
+#define SUPD 410
+#define UNIX
+#define UNX
+#define _DEBUG
+#define _PTHREADS
+#define _REENTRANT
+#define RTL_USING
+#define SYSTEM_ZLIB
+#define HAVE_GCC_VISIBILITY_FEATURE
+
+#import "time.h"
+
+typedef enum {IN,OUT} MLOFadeType;
+#define MLOFadeTypeString(enum) [@[@"IN",@"OUT"] objectAtIndex:enum]
+
+#define CGRECT_ZERO CGRectMake(0,0,0,0)
+#define CGRECT_ONE CGRectMake(1,1,1,1)
+static const CGFloat MLO_IPAD_HEIGHT_IN_PIXELS = 1024,
+ MLO_IPAD_WIDTH_IN_PIXELS = 768;
+
+
+#endif
diff --git a/ios/shared/ios_sharedlo/objective_c/utils/MLOObject.h b/ios/shared/ios_sharedlo/objective_c/utils/MLOObject.h
new file mode 100644
index 000000000000..2edadb79aa53
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/utils/MLOObject.h
@@ -0,0 +1,14 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOCommon.h"
+#import <Foundation/Foundation.h>
+
+@interface MLOObject : NSObject
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/utils/MLOObject.m b/ios/shared/ios_sharedlo/objective_c/utils/MLOObject.m
new file mode 100644
index 000000000000..daac1bd8acdc
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/utils/MLOObject.m
@@ -0,0 +1,13 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOObject.h"
+
+@implementation MLOObject
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/utils/MLOResourceImage.h b/ios/shared/ios_sharedlo/objective_c/utils/MLOResourceImage.h
new file mode 100644
index 000000000000..aac342710578
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/utils/MLOResourceImage.h
@@ -0,0 +1,32 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOObject.h"
+
+typedef enum {NORMAL,RETINA} MLOResourceImageSize;
+#define MLOResourceImageSizeString(enum) [@[@"NORMAL",@"RETINA"] objectAtIndex:enum]
+typedef enum {IMAGE, MASK} MLOResourceImageType;
+#define MLOResourceImageTypeString(enum) [@[@"MASK",@"RETINA"] objectAtIndex:enum]
+
+@interface MLOResourceImage : MLOObject
+-(NSString *)name;
+-(UIImage *)image;
+
++(MLOResourceImage *) backWithSize:(MLOResourceImageSize) size;
++(MLOResourceImage *) shrink;
++(MLOResourceImage *) expand;
++(MLOResourceImage *) edit;
++(MLOResourceImage *) find;
++(MLOResourceImage *) print;
++(MLOResourceImage *) save;
++(MLOResourceImage *) left;
++(MLOResourceImage *) right;
++(MLOResourceImage *) selectionHandle;
++(NSString *) magnifierName:(MLOResourceImageType) type;
++(UIImage *) loLogo;
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/utils/MLOResourceImage.m b/ios/shared/ios_sharedlo/objective_c/utils/MLOResourceImage.m
new file mode 100644
index 000000000000..016e36921430
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/utils/MLOResourceImage.m
@@ -0,0 +1,104 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOResourceImage.h"
+
+@interface MLOResourceImage ()
+
+@property NSString * name;
+@property UIImage * image;
+@end
+
+
+@implementation MLOResourceImage
+
++(MLOResourceImage *)imageWithName:(NSString *) name{
+ return [MLOResourceImage imageWithName:name size:NORMAL];
+}
+
++(MLOResourceImage *)imageWithName:(NSString *) name size:(MLOResourceImageSize) size{
+ MLOResourceImage * image = [MLOResourceImage new];
+ if(image){
+ image.name = name;
+ image.image = [MLOResourceImage getButtonImage:name size:size];
+ }
+ return image;
+}
+
++(UIImage *) getButtonImage:(NSString *) name size:(MLOResourceImageSize) size{
+ return [MLOResourceImage getImage: [@"Button" stringByAppendingString:name] size:size];
+}
+
++(UIImage *) getImage:(NSString *) midfix size:(MLOResourceImageSize) size{
+ return [UIImage imageNamed: [MLOResourceImage getImageName:midfix size:size]];
+}
+
++(NSString *) getImageName:(NSString *) midfix size:(MLOResourceImageSize) size{
+ return [NSString stringWithFormat: [MLOResourceImage formatForSize:size],midfix];
+}
++(NSString *) getImageName:(NSString *) midfix type:(MLOResourceImageType) type size:(MLOResourceImageSize) size{
+ return [MLOResourceImage getImageName: [midfix stringByAppendingString:[MLOResourceImage midfixSuffixForType:type]]
+ size: size];
+}
++(UIImage *) getImage:(NSString *) midfix type:(MLOResourceImageType) type size:(MLOResourceImageSize) size{
+ return [UIImage imageNamed: [MLOResourceImage getImageName:midfix type: type size:size]];
+}
+
++(NSString *) midfixSuffixForType:(MLOResourceImageType) type{
+ switch (type) {
+ case IMAGE: return @"";
+ case MASK: return @"Mask";
+ }
+}
+
+
++(NSString *) formatForSize:(MLOResourceImageSize) size{
+ switch (size) {
+ case NORMAL: return @"MLO%@.png";
+ case RETINA: return @"MLO%@@2x.png";
+ }
+}
+
++(UIImage *) loLogo{
+ return [self getImage:@"LibreOfficeLogo" size:NORMAL];
+}
+
++(MLOResourceImage *) backWithSize:(MLOResourceImageSize) size{
+ return [MLOResourceImage imageWithName:@"Back" size:size];
+}
++(MLOResourceImage *) shrink{
+ return [MLOResourceImage imageWithName:@"Shrink"];
+}
++(MLOResourceImage *) expand{
+ return [MLOResourceImage imageWithName:@"Expand"];
+}
++(MLOResourceImage *) edit{
+ return [MLOResourceImage imageWithName:@"Edit"];
+}
++(MLOResourceImage *) find{
+ return [MLOResourceImage imageWithName:@"Find"];
+}
++(MLOResourceImage *) print{
+ return [MLOResourceImage imageWithName:@"Print"];
+}
++(MLOResourceImage *) save{
+ return [MLOResourceImage imageWithName:@"Save"];
+}
++(MLOResourceImage *) left{
+ return [MLOResourceImage imageWithName:@"Left"];
+}
++(MLOResourceImage *) right{
+ return [MLOResourceImage imageWithName:@"Right"];
+}
++(MLOResourceImage *) selectionHandle{
+ return [MLOResourceImage imageWithName:@"SelectionHandle"];
+}
++(NSString *) magnifierName:(MLOResourceImageType) type{
+ return [MLOResourceImage getImageName:@"Magnifier" type:type size:RETINA];
+}
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/utils/MLOSubView.h b/ios/shared/ios_sharedlo/objective_c/utils/MLOSubView.h
new file mode 100644
index 000000000000..5b9e51d93764
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/utils/MLOSubView.h
@@ -0,0 +1,26 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import <UIKit/UIKit.h>
+#import "MLOCommon.h"
+
+typedef enum {ZERO, ONE, INITIAL,FULL_SCREEN} MLORectSize;
+#define MLORectSizeString(enum) [@[@"ZERO",@"ONE",@"INITIAL",@"FULL_SCREEN"] objectAtIndex:enum]
+
+@interface MLOSubView : UIView
+
+@property CGFloat fadeDuration;
+
+- (id)initWithFrame:(CGRect)frame color:(UIColor *) color cornerRadius:(CGFloat) cornerRadius alpha:(CGFloat) alpha;
+- (id)initHiddedWithColor:(UIColor *) color cornerRadius:(CGFloat) cornerRadius;
+- (id)initHiddedWithColor:(UIColor *) color;
+-(void)fade:(MLOFadeType) type;
+-(void)fadeToPercent:(CGFloat) toPercent;
+-(void)setSize:(MLORectSize) size;
+-(void) hide;
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/utils/MLOSubView.m b/ios/shared/ios_sharedlo/objective_c/utils/MLOSubView.m
new file mode 100644
index 000000000000..7362e0901fcc
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/utils/MLOSubView.m
@@ -0,0 +1,97 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOCommon.h"
+#import "MLOSubView.h"
+
+#import <QuartzCore/QuartzCore.h>
+
+#define SIZE_CASE(CASE,RECT) case CASE: self.frame = self.bounds = RECT;break;
+
+static const CGFloat DEFAULT_FADE_DURAION= 1.0f;
+
+@interface MLOSubView ()
+@property CGRect defaultRect;
+@end
+
+@implementation MLOSubView
+
+- (id)initWithFrame:(CGRect)frame color:(UIColor *) color cornerRadius:(CGFloat) cornerRadius alpha:(CGFloat) alpha
+{
+ self = [super initWithFrame:frame];
+ if (self) {
+ self.defaultRect = frame;
+ self.backgroundColor = color;
+ self.fadeDuration = DEFAULT_FADE_DURAION;
+
+ if([self isLegalNewAlpha:alpha]){
+ self.alpha = alpha;
+ }
+
+ if(cornerRadius >= 0){
+ [self.layer setCornerRadius:cornerRadius];
+ [self.layer setMasksToBounds:YES];
+ }
+ }
+ return self;
+}
+
+- (id)initHiddedWithColor:(UIColor *) color cornerRadius:(CGFloat) cornerRadius{
+
+ return [self initWithFrame:CGRECT_ZERO color:color cornerRadius:cornerRadius alpha: 0.0f];
+}
+
+- (id)initHiddedWithColor:(UIColor *) color{
+ return [self initHiddedWithColor:color cornerRadius:-1.0f];
+}
+
+
+-(BOOL)isLegalNewAlpha:(CGFloat) alpha{
+ return (alpha>=0) && (alpha<=1) && (alpha!= self.alpha);
+}
+
+
+-(void)fade:(MLOFadeType) type{
+ CGFloat alpha;
+ switch (type) {
+ case IN: alpha = 1.0f; break;
+ case OUT: alpha = 0.0f; break;
+ }
+ [self fadeToPercent:alpha];
+}
+
+
+-(void)setSize:(MLORectSize) size{
+
+ switch(size){
+ SIZE_CASE(ZERO, CGRECT_ZERO)
+ SIZE_CASE(ONE, CGRECT_ONE)
+ SIZE_CASE(INITIAL, _defaultRect)
+ SIZE_CASE(FULL_SCREEN, [[UIApplication sharedApplication] keyWindow].frame)
+ }
+}
+
+-(void) hide{
+ self.alpha=0;
+ [self setSize:ZERO];
+}
+
+-(void)fadeToPercent:(CGFloat) toPercent{
+ if([self isLegalNewAlpha:toPercent]){
+
+ [UIView animateWithDuration:1.0 animations:^{
+
+ self.alpha = toPercent;
+
+ }];
+ }
+}
+
+
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/utils/MLOViewController.h b/ios/shared/ios_sharedlo/objective_c/utils/MLOViewController.h
new file mode 100644
index 000000000000..71153c53d2d7
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/utils/MLOViewController.h
@@ -0,0 +1,14 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import <UIKit/UIKit.h>
+#import "MLOCommon.h"
+
+@interface MLOViewController : UIViewController
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/utils/MLOViewController.m b/ios/shared/ios_sharedlo/objective_c/utils/MLOViewController.m
new file mode 100644
index 000000000000..1ad72a2db1d3
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/utils/MLOViewController.m
@@ -0,0 +1,18 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOViewController.h"
+
+@interface MLOViewController ()
+
+@end
+
+@implementation MLOViewController
+
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/utils/NSObject+MLOUtils.h b/ios/shared/ios_sharedlo/objective_c/utils/NSObject+MLOUtils.h
new file mode 100644
index 000000000000..e1f883a3bd8e
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/utils/NSObject+MLOUtils.h
@@ -0,0 +1,16 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import <Foundation/Foundation.h>
+
+@interface NSObject (MLOUtils)
+-(CGRect) getFullFrameForRect:(CGRect) similarRect;
+-(void) performBlock:(void (^)(void))block
+ afterDelay:(NSTimeInterval)delay;
+-(BOOL)returnSuccees:(BOOL) success forAction:(NSString *) action andAlertForError:(NSError *) error;
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/utils/NSObject+MLOUtils.m b/ios/shared/ios_sharedlo/objective_c/utils/NSObject+MLOUtils.m
new file mode 100644
index 000000000000..67f213c56487
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/utils/NSObject+MLOUtils.m
@@ -0,0 +1,66 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "NSObject+MLOUtils.h"
+static CGFloat smaller = -1,bigger = -1;
+static CGRect portrait,landscape;
+
+@implementation NSObject (MLOUtils)
+
+-(void)fetchStatics{
+ if(smaller<0){
+ smaller = [UIScreen mainScreen].bounds.size.height;
+ bigger = [UIScreen mainScreen].bounds.size.width;
+ if(smaller> bigger){
+ NSInteger temp = bigger;
+ bigger= smaller;
+ smaller= temp;
+ }
+ portrait = CGRectMake(0, 0, smaller, bigger);
+ landscape = CGRectMake(0, 0, bigger, smaller);
+ }
+}
+
+-(CGRect) getFullFrameForRect:(CGRect) similarRect{
+ [self fetchStatics];
+ if(similarRect.size.width >smaller){
+
+ return landscape;
+ }
+ return portrait;
+}
+- (void)performBlock:(void (^)(void))block
+ afterDelay:(NSTimeInterval)delay
+{
+ [self performSelector:@selector(fireBlockAfterDelay:)
+ withObject:block
+ afterDelay:delay];
+}
+
+- (void)fireBlockAfterDelay:(void (^)(void))block {
+ block();
+}
+
+-(BOOL)returnSuccees:(BOOL) success forAction:(NSString *) action andAlertForError:(NSError *) error {
+ if(!success){
+
+ UIAlertView *failedDeleteAlert =
+ [[UIAlertView alloc]initWithTitle:@"Meh:"
+ message:[NSString stringWithFormat:@"Failed to perform: %@",action]
+ delegate:self
+ cancelButtonTitle:@"Close"
+ otherButtonTitles:nil];
+
+ [failedDeleteAlert show];
+
+ NSLog(@"Could not %@ :%@ ",action,[error localizedDescription]);
+ }
+ return success;
+}
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/MLOMainViewController.h b/ios/shared/ios_sharedlo/objective_c/view_controllers/MLOMainViewController.h
new file mode 100644
index 000000000000..ed34fd184c41
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/MLOMainViewController.h
@@ -0,0 +1,28 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOViewController.h"
+
+@class MLORenderManager,MLOSelectionViewController,MLOScrollerViewController,MLOKeyboardManager;
+@interface MLOMainViewController : MLOViewController<UITextViewDelegate>
+
+@property MLOSelectionViewController * selection;
+@property MLOScrollerViewController * scroller;
+@property MLOKeyboardManager * keyboard;
+@property UIView * canvas;
+
+-(void) rotate;
+-(void) showLibreOffice:(UIWindow *) window;
+-(void) onTextEdit;
+-(void) hideLibreOffice;
+-(BOOL) isTappable;
+-(void) flash;
+-(CGFloat) getZoom;
+@end
+
+// vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/MLOMainViewController.m b/ios/shared/ios_sharedlo/objective_c/view_controllers/MLOMainViewController.m
new file mode 100644
index 000000000000..cb29994a7a09
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/MLOMainViewController.m
@@ -0,0 +1,256 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOToolbarViewController.h"
+#import "MLOSelectionViewController.h"
+#import "MLOGestureEngine.h"
+#import "MLOScrollerViewController.h"
+#import "MLOManager.h"
+#import "MLOGestureLimiter.h"
+#import "MLOGestureEngine_Impl.h"
+#import "MLORenderManager.h"
+#import "NSObject+MLOUtils.h"
+#import "MLOTopbarViewController.h"
+#import "MLOMainViewController_Impl.h"
+#import "MLOKeyboardManager.h"
+#import "mlo_uno.h"
+
+@interface MLOMainViewController ()
+
+@property BOOL focused;
+@property CGFloat topBarHeight;
+@property UIView * flasher;
+@property MLOTopbarViewController * topbar;
+@property MLOToolbarViewController * toolbar;
+
+@end
+
+static const CGFloat
+ FLASH_DURATION= 0.2f,
+ EXPAND_DURATION=0.5f,
+ ROTATE_FLASH_DURATION=0.5f;
+
+@implementation MLOMainViewController
+
+-(void)onTextEdit{
+ [_scroller contentHasChanged];
+}
+
+-(BOOL)isTappable{
+ return [_toolbar isTappable];
+}
+
+-(void)showLibreOffice:(UIWindow *) window{
+
+ _topBarHeight = TOP_BAR_HEIGHT;
+ [[UIApplication sharedApplication]setStatusBarHidden:YES];
+
+ self.view.bounds = self.view.frame = [self getFullFrameForRect:self.view.frame];
+
+ [_renderManager setWidth:self.view.frame.size.width height:self.view.frame.size.height];
+
+ [_gestureEngine showLibreOffice:window];
+
+ [self onStart];
+
+ [_topbar showLibreOffice];
+ [_toolbar showLibreOffice];
+
+}
+
+-(void)onStart{
+ self.focused = YES;
+ [self rotate];
+}
+
+-(void) hideLibreOffice{
+ if(self.focused){
+
+ self.focused = NO;
+ [self.topbar hideLibreOffice];
+ [self.toolbar hideLibreOffice];
+
+ [self resetSubviews];
+
+ [[UIApplication sharedApplication]setStatusBarHidden:NO];
+
+ [self.gestureEngine hideLibreOffice];
+
+ [self.scroller hideLibreOffice];
+
+ [self.selection reset];
+
+ [self.keyboard hide];
+
+ [self.view removeFromSuperview];
+
+ [[MLOManager getInstance] hideLibreOffice];
+ }
+}
+
+-(void)initCanvas{
+
+ self.view.frame = self.view.bounds =[self getFullFrameForRect:[[MLOManager getInstance] bounds]];
+
+ self.canvas = [[UIView alloc]
+ initWithFrame:CGRectMake(0,
+ TOP_BAR_HEIGHT,
+ self.view.frame.size.width,
+ self.view.frame.size.height - TOP_BAR_HEIGHT)];
+ self.canvas.clipsToBounds = YES;
+ self.canvas.backgroundColor = [UIColor whiteColor];
+}
+
+- (id) init{
+ self = [super init];
+ if(self){
+
+ [self initCanvas];
+
+ self.scroller = [[MLOScrollerViewController alloc] initWithMainViewController:self];
+
+ self.selection = [[MLOSelectionViewController alloc] initWithMainViewController: self];
+
+ self.toolbar = [[MLOToolbarViewController alloc] initWithMainViewController:self];
+
+ self.topbar = [[MLOTopbarViewController alloc] initWithMainViewController:self];
+
+ self.flasher =[[UIView alloc] initWithFrame:CGRECT_ZERO];
+
+ self.keyboard = [[MLOKeyboardManager alloc]initWithMainViewController:self];
+
+ _flasher.alpha = 0.0f;
+ _flasher.backgroundColor = [UIColor whiteColor];
+
+ self.gestureEngine = nil;
+ [self addSubviews];
+
+ [self onStart];
+
+ _focused =NO;
+ _topBarHeight = TOP_BAR_HEIGHT;
+ }
+ return self;
+}
+
+-(void) flash{
+ _flasher.frame =self.view.frame;
+ _flasher.alpha = 1.0f;
+ [self.view addSubview:_flasher];
+ [UIView animateWithDuration:FLASH_DURATION animations:^{
+ _flasher.alpha=0.0f;
+ } completion:^(BOOL finished) {
+ [_flasher removeFromSuperview];
+ }];
+}
+
+-(void) toggleExpand{
+ CGFloat targetHeight = (_topBarHeight==0.0f)?TOP_BAR_HEIGHT:0.0f;
+ CGRect mainFrame = self.view.frame;
+
+ [UIView animateWithDuration:EXPAND_DURATION animations:^(void){
+
+ _canvas.frame = CGRectMake(0, targetHeight, mainFrame.size.width, mainFrame.size.height - targetHeight);
+ _renderManager.view.alpha= 0.0f;
+
+
+ } completion:^(BOOL completed){
+
+ _topBarHeight = targetHeight;
+ [self rotate];
+ [_toolbar expandDidToggle];
+ }];
+}
+
+-(void)resize{
+ CGRect mainViewRect = [self getFullFrameForRect:self.view.bounds];
+
+ LOG_RECT(mainViewRect, @"MLO Resize: main view");
+
+ self.view.bounds = self.view.frame = mainViewRect;
+
+ CGFloat width = self.view.frame.size.width;
+ CGFloat height = self.view.frame.size.height - _topBarHeight;
+
+ CGRect canvasRect =CGRectMake(0, _topBarHeight, width, height);
+
+ _canvas.frame = canvasRect;
+
+ [_renderManager setWidth:width height:height];
+
+ LOG_RECT(canvasRect, @"MLO Resize: canvas");
+
+
+}
+
+-(void) addSubviews{
+
+ [_topbar addToMainViewController];
+
+ [self.view addSubview:_canvas];
+
+ self.view.backgroundColor = [UIColor whiteColor];
+ self.renderManager = [MLORenderManager getInstance];
+
+ [self resize];
+
+ [self.canvas addSubview: _renderManager.view];
+
+ self.gestureEngine = [[MLOGestureEngine alloc] initWithMainViewController:self];
+ [_toolbar addToMainViewController];
+ [_scroller addToMainViewController];
+ [_selection addToMainViewController];
+ [_keyboard addToMainViewController];
+}
+
+-(void)rotate{
+ if(_focused){
+
+ NSLog(@"MLO rotate");
+
+ _renderManager.view.alpha= 0.0f;
+
+ [self resize];
+
+ [_gestureEngine onRotate];
+
+ [_topbar onRotate];
+
+ [_scroller reset];
+
+ [_scroller showLibreOffice];
+
+ [_selection onRotate];
+
+ [_toolbar onRotate];
+
+
+ [UIView animateWithDuration:ROTATE_FLASH_DURATION animations:^(void){
+ _renderManager.view.alpha=1.0f;
+ }];
+
+ }
+}
+
+
+
+-(void)resetSubviews{
+ [_gestureEngine reset];
+ [_scroller reset];
+ [_selection reset];
+}
+
+-(CGFloat) getZoom{
+ return [_gestureEngine.limiter zoom];
+}
+
+
+@end
+
+
+// vim:set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/MLOMainViewController_Impl.h b/ios/shared/ios_sharedlo/objective_c/view_controllers/MLOMainViewController_Impl.h
new file mode 100644
index 000000000000..fbb5af8bd501
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/MLOMainViewController_Impl.h
@@ -0,0 +1,18 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOMainViewController.h"
+
+static const CGFloat TOP_BAR_HEIGHT =40.0f;
+
+@class MLOGestureEngine,MLORenderManager;
+@interface MLOMainViewController ()
+@property MLOGestureEngine * gestureEngine;
+@property MLORenderManager * renderManager;
+-(void) toggleExpand;
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/MLOTopbarViewController.h b/ios/shared/ios_sharedlo/objective_c/view_controllers/MLOTopbarViewController.h
new file mode 100644
index 000000000000..4c10386a6098
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/MLOTopbarViewController.h
@@ -0,0 +1,17 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOObject.h"
+@class MLOMainViewController;
+@interface MLOTopbarViewController : MLOObject
+-(void)addToMainViewController;
+-(id)initWithMainViewController:(MLOMainViewController *) mainViewController;
+-(void)hideLibreOffice;
+-(void)showLibreOffice;
+-(void)onRotate;
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/MLOTopbarViewController.m b/ios/shared/ios_sharedlo/objective_c/view_controllers/MLOTopbarViewController.m
new file mode 100644
index 000000000000..0f5fe220a6df
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/MLOTopbarViewController.m
@@ -0,0 +1,93 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOTopbarViewController.h"
+#import "MLOMainViewController_Impl.h"
+#import "MLOMainViewController.h"
+#import "MLOButton.h"
+#import "MLOResourceImage.h"
+#import "MLOManager.h"
+
+@interface MLOTopbarViewController ()
+@property MLOMainViewController * mainViewController;
+@property UIView * blackbox;
+@property MLOButton * button;
+@property UILabel * label;
+@property MLOResourceImage * buttonImage;
+@end
+
+static const CGFloat
+ BUTTON_LEFT_SPACING = 18.0f,
+ FONT_SIZE = 15.0f;
+
+
+@implementation MLOTopbarViewController
+-(id)initWithMainViewController:(MLOMainViewController *) mainViewController{
+ self = [self init];
+ if(self){
+ self.mainViewController = mainViewController;
+
+ self.blackbox = [[UIView alloc] initWithFrame:CGRECT_ZERO];
+ _blackbox.backgroundColor = [UIColor blackColor];
+
+ self.label = [[UILabel alloc] initWithFrame:CGRECT_ZERO];
+ _label.textColor = [UIColor whiteColor];
+ _label.backgroundColor = [UIColor clearColor];
+ _label.textAlignment = NSTextAlignmentCenter;
+ _label.font =[UIFont systemFontOfSize:FONT_SIZE];
+
+ self.buttonImage = [MLOResourceImage backWithSize:NORMAL];
+ self.button = [MLOButton buttonWithImage:_buttonImage];
+ [_button addTarget:_mainViewController action:@selector(hideLibreOffice)];
+
+ [self hideLibreOffice];
+ }
+ return self;
+}
+-(void)addToMainViewController{
+ [_mainViewController.view addSubview:_blackbox];
+ [_mainViewController.view addSubview:_button];
+ [_mainViewController.view addSubview:_label];
+}
+
+-(void)hideLibreOffice{
+ _button.alpha =0.0f;
+ _button.alpha =0.0f;
+ _label.alpha =0.0f;
+ _blackbox.frame = CGRECT_ZERO;
+ _button.frame =CGRECT_ZERO;
+ _label.frame = CGRECT_ZERO;
+}
+
+-(void)showLibreOffice{
+ _blackbox.alpha= 1.0f;
+ _button.alpha = 1.0f;
+ _label.alpha=1.0f;
+ _label.text = [[MLOManager getInstance] filenameWithExtension];
+}
+
+-(void)onRotate{
+
+ CGFloat screenWidth = _mainViewController.view.frame.size.width;
+
+ _blackbox.frame = CGRectMake(0,0,screenWidth,TOP_BAR_HEIGHT);
+
+ _button.frame = CGRectMake(0,//BUTTON_LEFT_SPACING,
+ 0,//(TOP_BAR_HEIGHT - _buttonImage.image.size.height)/2.0f,
+ TOP_BAR_HEIGHT,// _buttonImage.image.size.width,
+ TOP_BAR_HEIGHT);// _buttonImage.image.size.height);
+
+ static const CGFloat
+ LABEL_Y = (TOP_BAR_HEIGHT - FONT_SIZE)/4.0f,
+ LABEL_HEIGHT = TOP_BAR_HEIGHT - LABEL_Y;
+
+ _label.frame = CGRectMake(BUTTON_LEFT_SPACING, LABEL_Y, screenWidth-BUTTON_LEFT_SPACING, LABEL_HEIGHT);
+}
+
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerData.h b/ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerData.h
new file mode 100644
index 000000000000..657dbc552f1a
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerData.h
@@ -0,0 +1,33 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOObject.h"
+
+static const CGFloat
+ PIXEL_TO_LOGIC_RATIO = 14.978,//513885/30/MLO_IPAD_HEIGHT_IN_PIXELS,
+ CANVAS_WIDTH_IN_LOGIC = 13000,
+ // NOTE:
+ // value keeps shifting between 14.975 and 14.984,
+ // though mostly it is on the 14.975 area
+
+ LO_PAGE_SEPARATOR_HEIGHT_IN_LOGIC = 18 * PIXEL_TO_LOGIC_RATIO,
+ LO_HORIZONAL_BORDER_WIDTH_IN_LOGIC = 18 * PIXEL_TO_LOGIC_RATIO,
+ PORTRAIT_PAGE_HEIGHT_IN_LOGIC_WITH_SEPARATOR = 513885 /30,
+ PORTRAIT_PAGE_HEIGHT_IN_LOGIC_WITHOUT_SEPARATOR = PORTRAIT_PAGE_HEIGHT_IN_LOGIC_WITH_SEPARATOR - LO_PAGE_SEPARATOR_HEIGHT_IN_LOGIC;
+
+@class MLOMainViewController, MLOScrollerTooltip,MLOScrollerGridViewController;
+@interface MLOScrollerData : MLOObject
+-(id)initWithMainViewController:(MLOMainViewController *) mainViewController;
+-(void) onRotateWithGrid:(MLOScrollerGridViewController *) grid;
+-(NSInteger) getTotalPages;
+-(CGRect) getNewScrollerFrame;
+-(CGRect) getShiftedScrollerFrame:(CGFloat) pixelDeltaX;
+-(void) updateTooltip:(MLOScrollerTooltip *) tooltip withGrid:(MLOScrollerGridViewController *) grid;
+-(void) showLibreOffice;
+-(void) hideLibreOffice;
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerData.m b/ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerData.m
new file mode 100644
index 000000000000..28ca6357514f
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerData.m
@@ -0,0 +1,209 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOScrollerData.h"
+#import "MLOMainViewController_Impl.h"
+#import "MLOGestureEngine_Impl.h"
+#import "MLOScrollerGridViewController.h"
+#import "MLOScrollerTooltip.h"
+#import "MLOGestureLimiter.h"
+#import "mlo_uno.h"
+#import "mlo_utils.h"
+
+@interface MLOScrollerData ()
+
+@property int left, top, zoom, visibleLeft, visibleTop, visibleRight, visibleBottom, zoomType, isBooklet;
+@property float totalPages, totalHeightInLogic, frameWidth, frameHeight, scrollerX, scrollerTotalHeight,tooltipPageHeight,tooltipX,tooltipMaxY;
+@property NSMutableString *mutableString;
+@property CGRect maxCanvas,contentCanvas,visibleCanvas;
+@property MLOMainViewController * mainViewController;
+
+@end
+
+static const float
+ SCROLLER_WIDTH=10,
+ SCROLLER_PADDING = 0,
+
+ GRID_TO_TOOLTIP_DISTANCE = 2.0f,
+
+ TOOLTIP_HEIGHT=60,
+ TOOLTIP_WIDTH=100,
+
+ FLOAT_RESET=-1.0f;
+
+static const int INT_RESET= -1;
+
+@implementation MLOScrollerData
+
+
+-(id)initWithMainViewController:(MLOMainViewController *) mainViewController{
+ self= [super init];
+ if(self){
+ self.mutableString = [NSMutableString stringWithString:@""];
+ self.mainViewController = mainViewController;
+ [self reset];
+ }
+ return self;
+}
+
+-(void) showLibreOffice{
+}
+
+-(void)hideLibreOffice{
+ [self reset];
+}
+
+-(void)reset{
+ _tooltipMaxY= _tooltipPageHeight = _tooltipX = _totalPages = _totalHeightInLogic = _frameWidth= _frameHeight= _scrollerX= _scrollerTotalHeight = FLOAT_RESET;
+ _left = _top = _zoom = _visibleLeft = _visibleTop = _visibleRight = _visibleBottom = _zoomType = _isBooklet = INT_RESET;
+
+}
+
+-(void) updateViewData{
+
+ mlo_fetch_view_data(_mutableString);
+
+ sscanf([_mutableString UTF8String], "%d;%d;%d;%d;%d;%d;%d;%d;%d;",
+ &_left,
+ &_top,
+ &_zoom,
+ &_visibleLeft,
+ &_visibleTop,
+ &_visibleRight,
+ &_visibleBottom,
+ &_zoomType,
+ &_isBooklet);
+
+ if(LOG_GET_VIEW_DATA){
+ NSLog(@"left=%d top=%d zoom=%d vLeft=%d vTop=%d vRight=%d vBottom=%d zoomType=%d isBooklet=%d",
+ _left,
+ _top,
+ _zoom,
+ _visibleLeft,
+ _visibleTop,
+ _visibleRight,
+ _visibleBottom,
+ _zoomType,
+ _isBooklet);
+ }
+}
+
+-(BOOL)canCalculateDocumentSizeInLogic{
+ return (_totalHeightInLogic != FLOAT_RESET);
+}
+
+-(void) onRotateWithGrid:(MLOScrollerGridViewController *) grid{
+ static const float SCROLLLER_X_OFFSET =SCROLLER_PADDING + SCROLLER_WIDTH ,
+ DOUBLE_SCROLLER_PADDING =2*SCROLLER_PADDING,
+ GRID_X_OFFSET= MLO_SCROLLER_GRID_WIDTH,
+ TOOLTIP_X_OFFSET= GRID_X_OFFSET + GRID_TO_TOOLTIP_DISTANCE+ TOOLTIP_WIDTH;
+
+ CGRect canvasFrame = _mainViewController.canvas.frame;
+
+ _frameHeight = canvasFrame.size.height;
+
+ _frameWidth = canvasFrame.size.width;
+
+ _scrollerX = _frameWidth - SCROLLLER_X_OFFSET;
+
+ _tooltipX = _frameWidth - TOOLTIP_X_OFFSET;
+
+ _tooltipMaxY = _frameHeight - TOOLTIP_HEIGHT;
+
+ _scrollerTotalHeight =_frameHeight -DOUBLE_SCROLLER_PADDING;
+
+ _tooltipPageHeight = _frameHeight/_totalPages;
+
+ [grid onRotate:_frameWidth - GRID_X_OFFSET];
+}
+
+-(NSInteger) getTotalPages{
+
+ NSInteger newTotalPages= mlo_get_pages(YES);
+
+ if(newTotalPages!= _totalPages){
+
+ _totalPages = newTotalPages;
+ _totalHeightInLogic = _totalPages* PORTRAIT_PAGE_HEIGHT_IN_LOGIC_WITH_SEPARATOR;
+
+ _tooltipPageHeight = _frameHeight/_totalPages;
+
+ _mainViewController.gestureEngine.limiter.documentSizeInLogic = CGSizeMake(CANVAS_WIDTH_IN_LOGIC,
+ _totalHeightInLogic);
+ }
+
+ return newTotalPages;
+}
+
+
+-(CGRect) getShiftedScrollerFrame:(CGFloat) pixelDeltaX{
+ pixelDeltaX *= PIXEL_TO_LOGIC_RATIO / [_mainViewController getZoom] * 100;
+ CGFloat newTop = _visibleTop + pixelDeltaX;
+ CGFloat newBottom = _visibleBottom + pixelDeltaX;
+
+ BOOL isOverTop = newTop < 0.0f;
+ BOOL isBelowBotton = newBottom > _totalHeightInLogic;
+
+ if(!isOverTop && !isBelowBotton){
+ _visibleTop = newTop;
+ _visibleBottom = newBottom;
+ }else{
+ CGFloat scrollerHeightInLogic = _visibleBottom- _visibleTop;
+ if(isOverTop){
+ _visibleTop = 0.0f;
+ _visibleBottom =scrollerHeightInLogic;
+ }else{
+ _visibleBottom = _totalHeightInLogic;
+ _visibleTop = _totalHeightInLogic - scrollerHeightInLogic;
+ }
+ }
+
+ return [self getNewScrollerFrame];
+}
+-(CGRect)getNewScrollerFrame{
+
+ [self updateViewData];
+
+ CGFloat topRatio = max(_visibleTop / _totalHeightInLogic,0.0);
+ CGFloat heightRatio = min((_visibleBottom / _totalHeightInLogic) - topRatio,1.0);
+
+ return CGRectMake(_scrollerX,
+ SCROLLER_PADDING +topRatio*_scrollerTotalHeight,
+ SCROLLER_WIDTH,
+ heightRatio*_scrollerTotalHeight);
+}
+-(NSInteger) getCurrentPage{
+
+ return min(
+ max(
+ ceilf(
+ _visibleTop
+ / PORTRAIT_PAGE_HEIGHT_IN_LOGIC_WITH_SEPARATOR
+ ),
+ 1),
+ _totalPages);
+}
+
+-(void) updateTooltip:(MLOScrollerTooltip *) tooltip withGrid:(MLOScrollerGridViewController *) grid{
+ if(mlo_is_document_open() && _visibleTop>=0){
+
+ NSInteger currentPage = [self getCurrentPage];
+
+ if(tooltip){
+
+ [tooltip updateWithFrame:CGRectMake(_tooltipX,
+ min(_tooltipPageHeight * (currentPage -1),_tooltipMaxY),
+ TOOLTIP_WIDTH,
+ TOOLTIP_HEIGHT) inPage:currentPage];
+ }
+ [grid onCurrentPageChanged:currentPage];
+ }
+}
+
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerGridViewController.h b/ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerGridViewController.h
new file mode 100644
index 000000000000..4fe3c62bac7d
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerGridViewController.h
@@ -0,0 +1,19 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOObject.h"
+
+static const CGFloat MLO_SCROLLER_GRID_WIDTH = 20.0f;
+@class MLOMainViewController;
+@interface MLOScrollerGridViewController : MLOObject
+-(id) initWithMainViewController:(MLOMainViewController *) mainViewController;
+-(void) hide;
+-(void) onCurrentPageChanged:(NSInteger) newCurrentPage;
+-(void) onPageCountChanged:(NSInteger) newPageCount;
+-(void)onRotate:(CGFloat) x;
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerGridViewController.m b/ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerGridViewController.m
new file mode 100644
index 000000000000..ce6ac5a7e94f
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerGridViewController.m
@@ -0,0 +1,136 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOScrollerGridViewController.h"
+#import "MLOMainViewController.h"
+
+static const CGFloat GRID_LINE_WIDTH=1.5f,
+ GRID_ACTUAL_WIDTH = MLO_SCROLLER_GRID_WIDTH- GRID_LINE_WIDTH,
+ UNSELECTED_ALPHA=0.05f,
+ SELECTED_ALPHA=0.15f;
+
+@interface MLOScrollerGridViewController ()
+@property MLOMainViewController * mainViewController;
+@property NSInteger pageCount,currentPage;
+@property CGFloat height,x,gridCellHeight;
+@property NSMutableArray * pages;
+@end
+
+@implementation MLOScrollerGridViewController
+
+
+-(void)hide{
+
+ [self resetMembers];
+
+ for(UIView * cell in _pages){
+ [cell removeFromSuperview];
+ cell.alpha=0.0f;
+ }
+
+ [_pages removeAllObjects];
+
+}
+
+-(void)resetMembers{
+ _pageCount=-1;
+ _currentPage=0;
+ _height=-1.0f;
+ _x=-1.0f;
+ _gridCellHeight=-1.0;
+}
+
+-(id) initWithMainViewController:(MLOMainViewController *) mainViewController{
+ self = [super init];
+ if (self) {
+ self.mainViewController = mainViewController;
+ [self resetMembers];
+ self.pages = [NSMutableArray new];
+ }
+ return self;
+}
+
+-(void)onRotate:(CGFloat) x{
+ _height =_mainViewController.canvas.frame.size.height;
+ _x=x;
+ [self reshape];
+}
+
+-(UIView *) getNewCell{
+ UIView * cell =[UIView new];
+
+ cell.backgroundColor = [UIColor blackColor];
+ cell.alpha = UNSELECTED_ALPHA;
+
+ [_mainViewController.canvas addSubview:cell];
+
+ return cell;
+}
+
+-(void)onPageCountChanged:(NSInteger) newPageCount{
+ if(_pageCount!=newPageCount){
+ _pageCount = newPageCount;
+
+ NSInteger currentSize = [_pages count];
+
+ NSInteger delta = abs(currentSize-newPageCount);
+
+ if(delta>0){
+ BOOL isAdd = currentSize< newPageCount;
+
+ for (NSInteger i=0; i<delta; i++) {
+
+ if(isAdd){
+
+ [_pages addObject:[self getNewCell]];
+
+ }else{
+ [_pages removeLastObject];
+ }
+ }
+
+ [self reshape];
+
+ if(!isAdd){
+ if(_currentPage > newPageCount){
+ [self onCurrentPageChanged:newPageCount];
+ }
+ }
+ }
+ }
+}
+
+-(void)reshape{
+ if((_x>=0) &&(_pageCount>0)){
+ _gridCellHeight= (_height - GRID_LINE_WIDTH*(_pageCount +1 ))/_pageCount;
+
+ CGFloat y = GRID_LINE_WIDTH;
+
+ for (UIView * cell in _pages){
+
+ cell.frame = CGRectMake(_x+GRID_LINE_WIDTH, y, GRID_ACTUAL_WIDTH, _gridCellHeight);
+
+ y+=_gridCellHeight +GRID_LINE_WIDTH;
+ }
+ }
+}
+
+-(void) onCurrentPageChanged:(NSInteger) newCurrentPage{
+ if(_currentPage!=newCurrentPage){
+ if( (_currentPage > 0) && ([_pages count] >= _currentPage)){
+ ((UIView *) [_pages objectAtIndex:_currentPage-1]).alpha = UNSELECTED_ALPHA;
+ }
+ if( (newCurrentPage > 0) && ([_pages count] >= newCurrentPage)){
+ ((UIView *) [_pages objectAtIndex:newCurrentPage -1]).alpha = SELECTED_ALPHA;
+ }
+ _currentPage = newCurrentPage;
+ }
+
+}
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerTooltip.h b/ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerTooltip.h
new file mode 100644
index 000000000000..3fc30c2c3c24
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerTooltip.h
@@ -0,0 +1,16 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import <UIKit/UIKit.h>
+
+@interface MLOScrollerTooltip : UITextView
+@property NSString * extension;
+-(void) updateWithFrame:(CGRect) newFrame inPage:(NSInteger) page;
+-(void) hide;
+-(void) hideLibreOffice;
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerTooltip.m b/ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerTooltip.m
new file mode 100644
index 000000000000..19a30ae37b97
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerTooltip.m
@@ -0,0 +1,78 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOCommon.h"
+#import "MLOScrollerTooltip.h"
+#import "MLOManager.h"
+#import <QuartzCore/QuartzCore.h>
+
+@interface MLOScrollerTooltip ()
+@property NSInteger lastPage;
+@end
+
+static const CGFloat BORDER_WIDTH = 1.0f,VISIBLE_ALPHA=0.85f;
+
+@implementation MLOScrollerTooltip
+
+- (id)init{
+
+ self = [super init];
+ if(self){
+
+ self.alpha= 0.0f;
+ self.frame =CGRECT_ONE;
+ self.backgroundColor = [UIColor whiteColor];
+
+ self.layer.borderWidth = BORDER_WIDTH;
+ self.layer.borderColor = [[UIColor grayColor] CGColor];
+
+ self.extension=nil;
+ _lastPage = -1;
+
+ self.textAlignment = NSTextAlignmentCenter;
+ self.textColor = [UIColor blackColor];
+ }
+ return self;
+}
+
+-(void) updateWithFrame:(CGRect) newFrame inPage:(NSInteger) page{
+
+ BOOL isForceUpdateFrame =NO;
+
+ if(_extension==nil){
+ self.extension = [[[MLOManager getInstance] extension] uppercaseString];
+
+ isForceUpdateFrame = YES;
+ }
+
+ if((self.frame.origin.y != newFrame.origin.y) || isForceUpdateFrame){
+
+ self.alpha=VISIBLE_ALPHA;
+
+ self.frame = newFrame;
+
+ self.text = [NSString stringWithFormat:@"Page %d This %@ is editable",page,_extension];
+
+ [self setNeedsDisplay];
+
+ _lastPage = page;
+ }
+
+}
+
+-(void) hide{
+ self.frame = self.bounds=CGRECT_ONE;
+ self.alpha = 0.0f;
+}
+
+-(void) hideLibreOffice{
+ self.extension = nil;
+}
+
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerViewController.h b/ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerViewController.h
new file mode 100644
index 000000000000..e6e313620d36
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerViewController.h
@@ -0,0 +1,26 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOObject.h"
+@class MLOScrollerData;
+@class MLOMainViewController;
+@interface MLOScrollerViewController : MLOObject
+@property MLOScrollerData * data;
+
+-(void)updateByLogic;
+-(void)updateByPixelDeltaY:(CGFloat) pixelDeltaY;
+-(void)contentHasChanged;
+-(void)onRotate;
+-(id)initWithMainViewController:(MLOMainViewController *) mainViewController;
+-(void) reset;
+-(void) fadeOut;
+-(void) addToMainViewController;
+-(void) hideLibreOffice;
+-(void) showLibreOffice;
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerViewController.m b/ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerViewController.m
new file mode 100644
index 000000000000..cbd9c025a289
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/scroller/MLOScrollerViewController.m
@@ -0,0 +1,157 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOScrollerViewController.h"
+#import "MLOMainViewController.h"
+#import "MLOSubView.h"
+#import "MLOScrollerData.h"
+#import "MLOScrollerTooltip.h"
+#import "MLOScrollerGridViewController.h"
+#import "mlo_uno.h"
+
+@interface MLOScrollerViewController ()
+@property BOOL isContentChanged,hasUpdated;
+@property MLOMainViewController * mainViewController;
+@property MLOSubView * scroller;
+@property MLOScrollerTooltip * tooltip;
+@property MLOScrollerGridViewController * grid;
+@property NSDate * fadeOutTime;
+@end
+
+static const CGFloat
+SCROLLER_CORNER_RADIUS =3.0f,
+RESHAPE_ANIMATION_DURATION= 0.05f,
+SCROLLER_FADE_OUT_DELAY=0.45f,
+SCROLLER_FADE_OUT_DURATION=1.0f,
+SCROLLER_FADE_OUT_INVOCATION =SCROLLER_FADE_OUT_DELAY+0.05f;
+
+// Tooltip is removed at request of PM
+// Maybe they'll want it back, or similar, in the future
+
+static const BOOL IS_SHOW_TOOLTIP =NO;
+
+@implementation MLOScrollerViewController
+
+-(id) initWithMainViewController:(MLOMainViewController *) mainViewController{
+ self = [super init];
+ if(self){
+ self.mainViewController = mainViewController;
+ self.scroller = [[MLOSubView alloc] initHiddedWithColor:[UIColor grayColor] cornerRadius:SCROLLER_CORNER_RADIUS];
+ self.data = [[MLOScrollerData alloc] initWithMainViewController:mainViewController];
+ if(IS_SHOW_TOOLTIP){
+ self.tooltip = [MLOScrollerTooltip new];
+ }else{
+ self.tooltip = nil;
+ }
+ self.fadeOutTime = nil;
+ self.grid = [[MLOScrollerGridViewController alloc] initWithMainViewController:mainViewController];
+ _isContentChanged =YES;
+ _hasUpdated =NO;
+
+ [_data onRotateWithGrid:_grid];
+ }
+ return self;
+}
+
+-(void) addToMainViewController{
+
+ [_mainViewController.canvas addSubview:_scroller];
+ [_mainViewController.canvas addSubview:_tooltip];
+}
+
+-(void) showLibreOffice{
+ [_data showLibreOffice];
+ [self contentHasChanged];
+
+ if(mlo_is_document_open()){
+ [self updateByLogic:NO];
+ }
+}
+
+-(void)contentHasChanged{
+ self.isContentChanged = YES;
+}
+
+-(void)onRotate{
+ [self contentHasChanged];
+ [_data onRotateWithGrid:_grid];
+
+}
+
+-(void)updateByLogic{
+ [self updateByLogic:YES];
+}
+
+-(void)updateByPixelDeltaY:(CGFloat) pixelDeltaY{
+
+ [self updateAndShowScroller:YES newScrollerFrame:[_data getShiftedScrollerFrame:pixelDeltaY]];
+}
+
+-(void)updateByLogic:(BOOL) isShow {
+
+ if(_isContentChanged){
+
+ [_grid onPageCountChanged:[_data getTotalPages]];
+
+ _isContentChanged=NO;
+ }
+
+ [self updateAndShowScroller:isShow newScrollerFrame:[_data getNewScrollerFrame]];
+}
+
+-(void)updateAndShowScroller:(BOOL) isShow newScrollerFrame:(CGRect) newScrollerFrame{
+
+ if(isShow){
+
+ _scroller.alpha = 0.5;
+ }
+ [UIView animateWithDuration:_hasUpdated ? RESHAPE_ANIMATION_DURATION :0.0f
+ animations:^{ _scroller.frame = newScrollerFrame; }
+ completion:^(BOOL isCompleted){
+
+ self.fadeOutTime = [NSDate dateWithTimeIntervalSinceNow:SCROLLER_FADE_OUT_DELAY];
+ [self performSelector:@selector(timedFadeOut) withObject:nil afterDelay:SCROLLER_FADE_OUT_INVOCATION];
+
+ }];
+
+ [_data updateTooltip:_tooltip withGrid:_grid];
+
+ _hasUpdated=YES;
+}
+
+
+-(void) reset{
+
+ [_scroller hide];
+ [_tooltip hide];
+
+ _hasUpdated=NO;
+ [self onRotate];
+}
+
+-(void) timedFadeOut {
+ NSDate * date = self.fadeOutTime;
+
+ if(![[date laterDate:[NSDate date]] isEqualToDate:date]){
+ [self fadeOut];
+ }
+}
+
+-(void)fadeOut{
+
+ [_scroller fade:OUT];
+}
+
+-(void) hideLibreOffice{
+ [_tooltip hideLibreOffice];
+ [_grid hide];
+ [self contentHasChanged];
+ [_data hideLibreOffice];
+}
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOContextualMenuFocus.h b/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOContextualMenuFocus.h
new file mode 100644
index 000000000000..5a86069fe04a
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOContextualMenuFocus.h
@@ -0,0 +1,17 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import <UIKit/UIKit.h>
+
+@class MLOSelectionViewController;
+@interface MLOContextualMenuFocus : UIView
+-(id)initWithSelectionViewController:(MLOSelectionViewController *) selectionViewController;
+-(void)loCopyToClipboard:(id) sender;
+-(void)loSelectAll:(id) sender;
+-(void)defineBuffer:(id) sender;
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOContextualMenuFocus.m b/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOContextualMenuFocus.m
new file mode 100644
index 000000000000..79ccd4d53566
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOContextualMenuFocus.m
@@ -0,0 +1,61 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOCommon.h"
+#import "MLOContextualMenuFocus.h"
+#import "MLOSelectionViewController_Impl.h"
+#import "mlo_uno.h"
+
+@interface MLOContextualMenuFocus ()
+@property MLOSelectionViewController * selectionViewController;
+@end
+@implementation MLOContextualMenuFocus
+
+-(id)initWithSelectionViewController:(MLOSelectionViewController *) selectionViewController{
+ self = [self init];
+ if(self){
+ self.selectionViewController = selectionViewController;
+ self.frame = CGRECT_ZERO;
+ self.backgroundColor = [UIColor clearColor];
+ }
+ return self;
+}
+
+-(void)loCopyToClipboard:(id) sender{
+ [UIPasteboard generalPasteboard].string =[_selectionViewController.buffer copy];
+
+}
+
+-(void)loSelectAll:(id) sender{
+
+ NSLog(@"Calling mlo_select_all()");
+ mlo_select_all();
+ NSLog(@"mlo_select_all() returned. reshowing contextualMenu");
+ [_selectionViewController showPostSelectAll];
+}
+
+
+-(void)defineBuffer:(id) sender{
+ [_selectionViewController defineBuffer];
+}
+
+-(NSString *) description{
+ return @"MLO contextual menu focus UIView";
+}
+- (BOOL) canPerformAction:(SEL)selector withSender:(id) sender {
+ if ((selector == @selector(loCopyToClipboard:)) ||
+ ((selector == @selector(loSelectAll:)) ||
+ (selector == @selector(defineBuffer:)))) {
+ return YES;
+ }
+ return NO;
+}
+- (BOOL) canBecomeFirstResponder {
+ return YES;
+}
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOMagnifier.h b/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOMagnifier.h
new file mode 100644
index 000000000000..e9ccc0515961
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOMagnifier.h
@@ -0,0 +1,20 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import <UIKit/UIKit.h>
+
+@class MLOMainViewController;
+@interface MLOMagnifier : UIView
+
+-(id) initWithMainViewController:(MLOMainViewController *) mainViewController;
+-(void) addToMainViewController;
+
+-(void) showAt:(CGPoint) point;
+-(void) hide;
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOMagnifier.m b/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOMagnifier.m
new file mode 100644
index 000000000000..3b7fbba593eb
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOMagnifier.m
@@ -0,0 +1,94 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOMainViewController_Impl.h"
+#import "MLOMagnifier.h"
+#import "MLOResourceImage.h"
+#import "MLORenderManager.h"
+#import <QuartzCore/QuartzCore.h>
+
+
+@interface MLOMagnifier ()
+@property CGPoint hotspot;
+@property MLOMainViewController * mainViewController;
+@property NSString * glassImageName,* maskImageName;
+@property BOOL shown,added;
+@end
+
+static const CGFloat MAGNIFIER_DIM = 160.0f,
+ HOTSPOT_TO_MAGNIFIER_DISTANCE= 66.0f;
+
+@implementation MLOMagnifier
+
+-(id) initWithMainViewController:(MLOMainViewController *) mainViewController{
+ self = [self initWithFrame:CGRectMake(MAGNIFIER_DIM,MAGNIFIER_DIM,MAGNIFIER_DIM,MAGNIFIER_DIM)];
+ if(self){
+ self.mainViewController = mainViewController;
+ self.layer.cornerRadius = MAGNIFIER_DIM / 2.0f;
+ self.layer.masksToBounds = YES;
+ self.glassImageName = [MLOResourceImage magnifierName:IMAGE];
+ self.maskImageName = [MLOResourceImage magnifierName:MASK];
+ self.shown = NO;
+ self.added = NO;
+ }
+ return self;
+}
+
+-(void) addToMainViewController{
+
+}
+
+
+-(void) showAt:(CGPoint) point{
+ if(!self.shown){
+ self.shown = YES;
+ [_mainViewController.canvas addSubview:self];
+ }
+
+ self.hotspot = point;
+
+ self.center = CGPointMake(point.x, point.y-HOTSPOT_TO_MAGNIFIER_DISTANCE);
+
+ [self setNeedsDisplay];
+
+}
+-(void) hide{
+
+ if(self.shown){
+ self.shown =NO;
+ [self removeFromSuperview];
+ }
+
+ self.center = CGPointMake(2*MAGNIFIER_DIM, 2*MAGNIFIER_DIM);
+
+}
+
+
+- (void)drawRect:(CGRect)rect
+{
+ CGContextRef context = UIGraphicsGetCurrentContext();
+ UIImage * glass = [UIImage imageNamed:_glassImageName];
+ // CGImageRef mask = [UIImage imageNamed:_maskImageName].CGImage;
+ CGRect bounds = self.bounds;
+
+ CGContextSaveGState(context);
+ //CGContextClipToMask(context, bounds, mask);
+ CGContextFillRect(context, bounds);
+ CGContextScaleCTM(context, 1.2, 1.2);
+
+ //draw your subject view here
+ CGContextTranslateCTM(context,1*(self.frame.size.width*0.5),1*(self.frame.size.height*0.5));
+ //CGContextScaleCTM(context, 1.5, 1.5);
+ CGContextTranslateCTM(context,-1*(self.hotspot.x),-1*(self.hotspot.y));
+ [_mainViewController.renderManager renderInContext:context];
+
+ CGContextRestoreGState(context);
+ [glass drawInRect: bounds];
+}
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOSelectionHandle.h b/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOSelectionHandle.h
new file mode 100644
index 000000000000..409164ad725b
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOSelectionHandle.h
@@ -0,0 +1,22 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+typedef enum {TOP_LEFT,BOTTOM_RIGHT} MLOSelectionHandleType;
+#define MLOSelectionHandleTypeString(enum) [@[@"TOP_LEFT",@"BOTTOM_RIGHT"] objectAtIndex:enum]
+
+@class MLOSelectionViewController;
+@interface MLOSelectionHandle : UIView
+
+-(id)initWithType:(MLOSelectionHandleType) type selection:(MLOSelectionViewController *) selectionViewController;
+-(void)addToMainViewController;
+-(void)showAt:(CGPoint) edge;
+-(void)hide;
+-(void)onRotate;
+-(CGPoint)getPivot;
+-(BOOL)handleMoveAtPoint:(CGPoint) center gestureState:(UIGestureRecognizerState) state;
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOSelectionHandle.m b/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOSelectionHandle.m
new file mode 100644
index 000000000000..30e60f84f870
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOSelectionHandle.m
@@ -0,0 +1,168 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOSelectionHandle.h"
+#import "MLOMainViewController_Impl.h"
+#import "MLOSelectionViewController_Impl.h"
+#import "MLOGestureEngine_Impl.h"
+#import "MLOResourceImage.h"
+
+@interface MLOSelectionHandle ()
+@property MLOSelectionViewController * selection;
+@property CGPoint lineTop, pivot;
+@property BOOL tracking;
+@end
+
+static const CGFloat LINE_HEIGHT = 20.0f,
+ LINE_WIDTH = 2.0f,
+ LINE_TO_HANDLE_SPACING=7.0f,
+ LINE_THICKNESS_PADDING = 3.0f,
+ HANDLE_THICKNESS_PADDING = 15.0f,
+ EXTERNAL_PADDING = 3.0f,
+ SIDE_PADDING = 15.0f,
+ VERTICAL_PADDING = HANDLE_THICKNESS_PADDING + LINE_THICKNESS_PADDING,
+ HORIZONAL_PADDING = SIDE_PADDING * 2.0f;
+
+@implementation MLOSelectionHandle
+
+-(id)initWithType:(MLOSelectionHandleType) type selection:(MLOSelectionViewController *) selectionViewController{
+ self = [self init];
+ if(self){
+
+ self.selection = selectionViewController;
+ self.backgroundColor = [UIColor clearColor];
+
+ MLOResourceImage * handleImage = [MLOResourceImage selectionHandle];
+
+ CGFloat handleWidth = handleImage.image.size.width;
+ CGFloat handleHeight = handleImage.image.size.height;
+ CGFloat handleHeightWithSpacingToLine = LINE_TO_HANDLE_SPACING + handleHeight;
+ CGFloat frameWidth = HORIZONAL_PADDING + handleWidth;
+
+ CGFloat lineYOrigin;
+ CGFloat handleYOrigin;
+ CGFloat pivotY;
+
+ switch (type) {
+ case TOP_LEFT:
+ handleYOrigin = HANDLE_THICKNESS_PADDING;
+ pivotY = handleYOrigin + LINE_HEIGHT;
+ lineYOrigin = pivotY + LINE_TO_HANDLE_SPACING;
+ break;
+
+ case BOTTOM_RIGHT:
+ lineYOrigin = LINE_THICKNESS_PADDING;
+ pivotY = lineYOrigin + LINE_HEIGHT;
+ handleYOrigin = pivotY+ LINE_TO_HANDLE_SPACING;
+ break;
+ }
+
+ self.frame = CGRectMake(0,
+ 0,
+ frameWidth,
+ VERTICAL_PADDING + LINE_HEIGHT + handleHeightWithSpacingToLine);
+
+ self.lineTop = CGPointMake(SIDE_PADDING + ((handleWidth - LINE_WIDTH) / 2.0f),
+ lineYOrigin);
+
+ self.pivot = CGPointMake(frameWidth/2.0f,
+ pivotY);
+
+ UIImageView * handle = [[UIImageView alloc] initWithImage:handleImage.image];
+
+ [self addSubview: handle];
+ handle.frame = CGRectMake(SIDE_PADDING,
+ handleYOrigin,
+ handleWidth,
+ handleHeight);
+ self.alpha = 0.0f;
+ self.tracking =NO;
+ }
+ return self;
+}
+-(void)addToMainViewController{
+ [_selection.mainViewController.canvas addSubview:self];
+
+
+}
+-(CGPoint) getPivot{
+ return CGPointMake(self.frame.origin.x + _pivot.x, self.frame.origin.y + _pivot.y);
+}
+-(void)showAt:(CGPoint) edge{
+
+ [self putAt:edge withAlpha:1.0f];
+}
+
+-(void)putAt:(CGPoint) center withAlpha:(CGFloat) alpha{
+ self.frame = CGRectMake(center.x - _pivot.x,
+ center.y - _pivot.y,
+ self.frame.size.width,
+ self.frame.size.height);
+ self.alpha = alpha;
+}
+
+-(void)hide{
+ [self putAt:CGPointMake(0,0) withAlpha:0.0f];
+}
+
+-(void)onRotate{
+ [self hide];
+}
+-(void)drawRect:(CGRect)rect{
+ [super drawRect:rect];
+
+ CGContextRef context = UIGraphicsGetCurrentContext();
+ CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
+
+ CGContextSetLineWidth(context, LINE_WIDTH);
+
+ CGContextMoveToPoint(context, _lineTop.x,_lineTop.y); //start at this point
+
+ CGContextAddLineToPoint(context, _lineTop.x, _lineTop.y + LINE_HEIGHT); //draw to this point
+
+ CGContextStrokePath(context); // draw the path
+}
+
+-(BOOL)handleMoveAtPoint:(CGPoint) center gestureState:(UIGestureRecognizerState) state{
+ if((self.alpha==0.0f)||
+ !CGRectContainsPoint(self.frame, center)){
+
+ [self endTracking];
+
+ return NO;
+ }
+
+ if (state == UIGestureRecognizerStateChanged) {
+ self.tracking = YES;
+ [self showAt:center];
+
+ _selection.finger = center;
+
+ [_selection reselect:NO];
+
+ }else if((state == UIGestureRecognizerStateEnded) ||
+ (state == UIGestureRecognizerStateCancelled) ||
+ (state == UIGestureRecognizerStateFailed)){
+
+ _selection.finger = center;
+
+ [self endTracking];
+ }
+ return YES;
+}
+
+-(void)endTracking{
+ if(self.tracking){
+ self.tracking=NO;
+
+ [_selection reselect:YES];
+
+ }
+}
+@end
+
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOSelectionViewController.h b/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOSelectionViewController.h
new file mode 100644
index 000000000000..081dd5f0c7ff
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOSelectionViewController.h
@@ -0,0 +1,22 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOObject.h"
+
+@class MLOMainViewController;
+@interface MLOSelectionViewController : MLOObject
+
+-(id)initWithMainViewController:(MLOMainViewController *) mainViewController;
+-(void)addToMainViewController;
+-(void)reset;
+-(void) onRotate;
+-(void) showBetweenFinger:(CGPoint) finger andPreviousPoint:(CGPoint) previousPoint showMenu:(BOOL) showMenu;
+-(void) showPostSelectAll;
+-(void) hide;
+-(BOOL)handleMoveAtPoint:(CGPoint) center gestureState:(UIGestureRecognizerState) state;
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOSelectionViewController.m b/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOSelectionViewController.m
new file mode 100644
index 000000000000..84b2be0aba56
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOSelectionViewController.m
@@ -0,0 +1,231 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOMainViewController_Impl.h"
+#import "MLOSelectionViewController_Impl.h"
+#import "MLOContextualMenuFocus.h"
+#import "MLOSelectionHandle.h"
+#import "MLOMagnifier.h"
+#import "MLORenderManager.h"
+#import "MLOThesaurusViewController.h"
+#import "mlo_utils.h"
+#import "mlo_uno.h"
+#include <touch/touch.h>
+
+@interface MLOSelectionViewController ()
+@property MLOContextualMenuFocus * focus;
+@property MLOSelectionHandle * topLeft, * bottomRight;
+@property MLOMagnifier * magnifier;
+@property BOOL menuShown,magnifierShown;
+@end
+
+static const CGFloat FOCUS_DIM=20.0f;
+
+@implementation MLOSelectionViewController
+
+-(id) initWithMainViewController:(MLOMainViewController *)mainViewController{
+ self = [super init];
+ if(self){
+ self.mainViewController = mainViewController;
+ self.buffer = [NSMutableString stringWithString:@""];
+ self.focus = [[MLOContextualMenuFocus alloc] initWithSelectionViewController:self];
+ self.topLeft = [[MLOSelectionHandle alloc] initWithType: TOP_LEFT selection:self];
+ self.bottomRight = [[MLOSelectionHandle alloc] initWithType: BOTTOM_RIGHT selection:self];
+ self.magnifier = [[MLOMagnifier alloc] initWithMainViewController:mainViewController];
+ self.menuShown =NO;
+ self.magnifierShown =NO;
+ self.finger = CGPointMake(0,0);
+ }
+
+ return self;
+}
+-(void) addToMainViewController{
+ [_mainViewController.canvas addSubview:_focus];
+ [_topLeft addToMainViewController];
+ [_bottomRight addToMainViewController];
+ [_magnifier addToMainViewController];
+}
+
+-(void) reset{
+ [self hide:NO];
+}
+-(UIMenuItem *)copyItem{
+ return [[UIMenuItem alloc]
+ initWithTitle: @"Copy"
+ action: @selector(loCopyToClipboard:)];
+}
+-(UIMenuItem *)selectAllItem{
+ return [[UIMenuItem alloc]
+ initWithTitle: @"Select All"
+ action: @selector(loSelectAll:)];
+}
+
+-(UIMenuItem *)defineItem{
+ return [[UIMenuItem alloc]
+ initWithTitle: @"Define"
+ action: @selector(defineBuffer:)];
+}
+
+-(void) showMenuAtCenter:(CGPoint)center{
+ [self showAtCenter:center selectAll:YES];
+}
+
+-(void) showPostSelectAll{
+
+ [self hideTouchTrackers];
+ [self showAtCenter:CGPointMake(_mainViewController.canvas.frame.size.width / 2.0f, FOCUS_DIM) selectAll:NO];
+}
+
+-(void) showAtTopLeft:(CGPoint) topLeft bottomRight:(CGPoint) bottomRight showMenu:(BOOL) showMenu{
+ [_topLeft showAt:topLeft];
+ [_bottomRight showAt:bottomRight];
+ if(showMenu){
+ [self hideMagnifier];
+ [self showMenuAtCenter:CGPointMake( (bottomRight.x + bottomRight.x) /2.0f,
+ (bottomRight.y + bottomRight.y) /2.0f)];
+ self.menuShown = YES;
+ }else{
+ [self hideMenu:YES];
+ [_magnifier showAt:self.finger];
+ self.magnifierShown=YES;
+ }
+
+ [_mainViewController.renderManager renderNow];
+}
+
+-(void) showBetweenFinger:(CGPoint) finger andPreviousPoint:(CGPoint) previousPoint showMenu:(BOOL) showMenu{
+ self.finger = finger;
+ [self showBetweenPointA:finger andPointB:previousPoint showMenu:showMenu];
+}
+
+-(void) showBetweenPointA:(CGPoint) pointA andPointB:(CGPoint) pointB showMenu:(BOOL) showMenu{
+
+ if((pointA.y < pointB.y) ||
+ ((pointA.y == pointB.y) && (pointA.x < pointB.x))){
+
+ [self showAtTopLeft:pointA bottomRight:pointB showMenu:showMenu];
+ }else{
+ [self showAtTopLeft:pointB bottomRight:pointA showMenu:showMenu];
+ }
+}
+
+-(void)showAtCenter:(CGPoint) center selectAll:(BOOL) isSelectAll{
+
+ CGFloat width = _mainViewController.canvas.frame.size.width;
+ CGFloat height = _mainViewController.canvas.frame.size.height;
+
+ self.focus.frame = CGRectMake( min(max(0,center.x - FOCUS_DIM),width - FOCUS_DIM),
+ min(max(0,center.y - FOCUS_DIM),height - FOCUS_DIM),
+ FOCUS_DIM,
+ FOCUS_DIM);
+
+ [self.focus becomeFirstResponder];
+
+ UIMenuController *menuController = [UIMenuController sharedMenuController];
+
+ [menuController setMenuItems:[self getMenuItems:isSelectAll]];
+
+ [menuController setTargetRect:self.focus.frame
+ inView:_mainViewController.canvas];
+ [menuController setMenuVisible:YES animated:YES];
+}
+
+-(NSArray *)getMenuItems:(BOOL) isSelectAll{
+
+ mlo_get_selection(_buffer);
+
+ NSLog(@"Copied LO selection to keyboard: %@",_buffer);
+
+ if(isSelectAll){
+
+ if([UIReferenceLibraryViewController dictionaryHasDefinitionForTerm:_buffer]){
+ NSLog(@"Creating contextual menu with Copy, Select All, and Define");
+
+ return @[[self copyItem], [self selectAllItem], [self defineItem]];
+
+ }
+ NSLog(@"Creating contextual menu with Copy and Select All");
+
+ return @[[self copyItem],[self selectAllItem]];
+ }
+
+ NSLog(@"Creating contextual menu with Copy only");
+
+ return @[[self copyItem]];
+ }
+
+-(NSString *)description{
+ return @"MLO contextual menu view controller";
+}
+
+-(void) hide{
+ [self hide:YES];
+}
+
+-(void) hideTouchTrackers{
+ [_topLeft hide];
+ [_bottomRight hide];
+ [self hideMagnifier];
+}
+
+-(void) hideMenu:(BOOL) animate{
+ if(self.menuShown){
+ self.menuShown =NO;
+ [[UIMenuController sharedMenuController] setMenuVisible:NO animated:animate];
+ }
+}
+
+-(void) hideMagnifier{
+ if(self.magnifierShown){
+ self.magnifierShown =NO;
+ [_magnifier hide];
+ }
+}
+
+-(void) hide:(BOOL) animate{
+
+ [self hideTouchTrackers];
+
+ [self hideMenu:animate];
+
+ [self.focus resignFirstResponder];
+ self.focus.frame =CGRECT_ZERO;
+}
+
+-(void)reselect:(BOOL) showMenu{
+
+ CGPoint pointA = [_topLeft getPivot];
+ CGPoint pointB = [_bottomRight getPivot];
+
+ touch_lo_mouse_drag(pointA.x, pointA.y, DOWN);
+
+ touch_lo_mouse_drag(pointB.x, pointB.y, MOVE);
+
+ touch_lo_mouse_drag(pointB.x, pointB.y, UP);
+
+ [self showBetweenPointA:pointA andPointB:pointB showMenu:showMenu];
+}
+
+-(void) onRotate{
+ [self reset];
+
+}
+
+-(BOOL)handleMoveAtPoint:(CGPoint) center gestureState:(UIGestureRecognizerState) state{
+ return (self.focus.frame.origin.x != 0) &&
+ ([_topLeft handleMoveAtPoint:center gestureState:state] ||
+ [_bottomRight handleMoveAtPoint:center gestureState:state]);
+}
+
+
+-(void)defineBuffer{
+ [[[MLOThesaurusViewController alloc] initWithSelectionViewController:self] show];
+
+}
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOSelectionViewController_Impl.h b/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOSelectionViewController_Impl.h
new file mode 100644
index 000000000000..670dcab7e7c6
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOSelectionViewController_Impl.h
@@ -0,0 +1,17 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOSelectionViewController.h"
+@class MLOMainViewController;
+@interface MLOSelectionViewController ()
+@property MLOMainViewController * mainViewController;
+@property NSMutableString * buffer;
+@property CGPoint finger;
+-(void)reselect:(BOOL) showMenu;
+-(void)defineBuffer;
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOThesaurusViewController.h b/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOThesaurusViewController.h
new file mode 100644
index 000000000000..299d2dbe2ef5
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOThesaurusViewController.h
@@ -0,0 +1,15 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import <UIKit/UIKit.h>
+@class MLOSelectionViewController;
+@interface MLOThesaurusViewController : UIReferenceLibraryViewController
+
+-(id) initWithSelectionViewController:(MLOSelectionViewController *) selectionViewController;
+-(void)show;
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOThesaurusViewController.m b/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOThesaurusViewController.m
new file mode 100644
index 000000000000..506e58654ddf
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/selection/MLOThesaurusViewController.m
@@ -0,0 +1,48 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOThesaurusViewController.h"
+#import "MLOSelectionViewController_Impl.h"
+#import "MLOMainViewController_Impl.h"
+#import "MLOGestureEngine_Impl.h"
+
+static const CGFloat THESAURUS_PADDING = 100.0f;
+@interface MLOThesaurusViewController ()
+@property MLOSelectionViewController * selection;
+@end
+
+@implementation MLOThesaurusViewController
+
+
+-(id) initWithSelectionViewController:(MLOSelectionViewController *) selectionViewController{
+ self = [self initWithTerm:selectionViewController.buffer];
+ if(self){
+ self.selection = selectionViewController;
+ self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
+ self.modalPresentationStyle = UIModalPresentationFormSheet;
+ }
+ return self;
+}
+
+-(void)show{
+ static const CGFloat TWO_PADDINGS = THESAURUS_PADDING*2.0;
+ self.view.frame = CGRectMake(THESAURUS_PADDING,
+ THESAURUS_PADDING,
+ _selection.mainViewController.canvas.frame.size.width - TWO_PADDINGS ,
+ _selection.mainViewController.canvas.frame.size.height - TWO_PADDINGS);
+
+ _selection.mainViewController.gestureEngine.focused = NO;
+ [_selection.mainViewController presentViewController:self animated:YES completion:nil];
+
+}
+
+-(void)viewDidDisappear:(BOOL)animated{
+ _selection.mainViewController.gestureEngine.focused = YES;
+ [_selection reselect:YES];
+}
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOFinder.h b/ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOFinder.h
new file mode 100644
index 000000000000..c7d97136fc24
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOFinder.h
@@ -0,0 +1,18 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOObject.h"
+
+@class MLOToolbarButton,MLOMainViewController;
+@interface MLOFinder : MLOObject
+-(id)initWithToolbarButton:(MLOToolbarButton *) findButton;
+-(void)addToMainViewController:(MLOMainViewController *)mainViewController;
+-(void)show;
+-(void)hide;
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOFinder.m b/ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOFinder.m
new file mode 100644
index 000000000000..37d7887cbc64
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOFinder.m
@@ -0,0 +1,281 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOFinder.h"
+#import "MLOToolbarButton.h"
+#import "MLOButton.h"
+#import "MLOMainViewController_Impl.h"
+#import "MLOGestureEngine_Impl.h"
+#import "MLORenderManager.h"
+#import "MLOSubView.h"
+#import "MLOResourceImage.h"
+#import "mlo_uno.h"
+
+@interface MLOFinder ()
+@property MLOSubView * blackBox;
+@property UILabel * label;
+@property UITextField * textField;
+@property NSString * lastSearched;
+@property NSDate * findTime;
+@property MLOButton * leftButton,* rightButton;
+@property NSInteger selectionCount,selectedIndex;
+@property MLOMainViewController * mainViewController;
+@end
+
+static const NSTimeInterval
+
+ NAVIGATION_BUTTON_FADE_DURATION = 1.0f,
+ FIND_DELAY = 1.0,
+ FIND_INVOCATION=FIND_DELAY+0.01;
+
+static const CGFloat
+ FADE_DURATION = 0.5f,
+ FADE_IN_TARGET = 1.0f,
+ FADE_OUT_TARGET = 0.0f,
+
+ TEXT_AREA_WIDTH = 150.0f,
+ SPACING_FROM_FIND_TOOLBAR_BUTTON=50.0f,
+ BLACK_BOX_CORNER_RADIUS=15.0f,
+
+ BLACK_BOX_INNER_PADDING_X = 10.0f,
+ BLACK_BOX_INNER_PADDING_Y = 10.0f,
+ TEXT_AREA_TO_NAVIAGATION_BUTTONS_SPACING = 5.0f,
+
+ LABEL_HEIGHT = 18.0f,
+ LABEL_TO_INPUT_FIELD_PADDING=8.0f,
+
+ INPUT_FIELD_HEIGHT = 20.0f,
+
+ BLACK_BOX_INNER_HEIGHT =LABEL_HEIGHT + LABEL_TO_INPUT_FIELD_PADDING + INPUT_FIELD_HEIGHT,
+ BLACK_BOX_HEIGHT=2*BLACK_BOX_INNER_PADDING_Y + BLACK_BOX_INNER_HEIGHT;
+
+@implementation MLOFinder
+
+-(id)initWithToolbarButton:(MLOToolbarButton *) findButton{
+
+ self = [super init];
+ if(self){
+
+ self.selectedIndex = -1;
+ self.selectionCount = -1;
+
+ MLOResourceImage * leftButtonImage = [MLOResourceImage left];
+ MLOResourceImage * rightButtonImage =[MLOResourceImage right];
+
+ CGFloat leftButtonWidth =leftButtonImage.image.size.width;
+ CGFloat rightButtonWidth = rightButtonImage.image.size.width;
+
+ CGRect findButtonFrame = findButton.frame;
+
+ CGFloat xOrigin = findButtonFrame.origin.x + findButtonFrame.size.width + SPACING_FROM_FIND_TOOLBAR_BUTTON;
+ CGFloat yOrigin = findButtonFrame.origin.y;
+
+ CGFloat leftButtonXOrigin = xOrigin + BLACK_BOX_INNER_PADDING_X;
+
+ CGFloat textAreaXOrigin = leftButtonXOrigin +leftButtonWidth + TEXT_AREA_TO_NAVIAGATION_BUTTONS_SPACING;
+ CGFloat textAreaYOrigin = yOrigin +BLACK_BOX_INNER_PADDING_Y;
+
+ CGFloat rightButtonXOrigin = textAreaXOrigin + TEXT_AREA_WIDTH + TEXT_AREA_TO_NAVIAGATION_BUTTONS_SPACING;
+
+ [self addBlackBoxXOrigin: xOrigin
+ yOrigin: yOrigin
+ width: leftButtonWidth +
+ rightButtonWidth +
+ (TEXT_AREA_TO_NAVIAGATION_BUTTONS_SPACING + BLACK_BOX_INNER_PADDING_X)*2 +
+ TEXT_AREA_WIDTH ];
+
+
+ [self addLabelXOrigin:textAreaXOrigin yOrigin:textAreaYOrigin];
+ [self addTextFieldXOrigin:textAreaXOrigin yOrigin:textAreaYOrigin];
+
+ self.leftButton =
+ [self addButtonXOrigin:leftButtonXOrigin
+ yOrigin:textAreaYOrigin
+ image:leftButtonImage
+ selector:@selector(onTapLeft)
+ name:@"left (previous)"];
+
+ self.rightButton =
+ [self addButtonXOrigin:rightButtonXOrigin
+ yOrigin:textAreaYOrigin
+ image:rightButtonImage
+ selector:@selector(onTapRight)
+ name:@"right (next)"];
+
+ self.lastSearched = @"";
+ self.findTime = [NSDate date];
+ }
+ return self;
+}
+-(void) onTapLeft{
+ [self onTap:MARK_PREVIOUS];
+}
+-(void) onTapRight{
+ [self onTap:MARK_NEXT];
+}
+
+-(void) onTap:(MLOFindSelectionType) type{
+ self.selectedIndex = mlo_find(_lastSearched, type);
+ [self updateLabel];
+
+}
+
+-(void)updateLabel{
+ CGFloat navigationAlpha;
+ if(_selectionCount>0){
+ self.label.text = [NSString stringWithFormat: @"Find (%d of %d)",_selectedIndex + 1,_selectionCount];
+ navigationAlpha = 1.0f;
+
+ }else{
+
+ self.label.text = @"Find";
+ navigationAlpha = 0.0f;
+ }
+
+ [self.mainViewController.gestureEngine.renderer renderNow];
+
+ if(_leftButton.alpha != navigationAlpha){
+ [UIView animateWithDuration:NAVIGATION_BUTTON_FADE_DURATION animations:^{
+ _leftButton.alpha = navigationAlpha;
+ _rightButton.alpha = navigationAlpha;
+
+ }];
+ }
+
+}
+
+-(MLOButton *) addButtonXOrigin:(CGFloat) xOrigin yOrigin:(CGFloat) yOrigin image:(MLOResourceImage *) image selector:(SEL) selector name:(NSString *) buttonName{
+ MLOButton * button = [MLOButton buttonWithImage:image];
+
+ CGFloat height = image.image.size.height;
+
+ if(height < BLACK_BOX_INNER_HEIGHT){
+ yOrigin += (BLACK_BOX_INNER_HEIGHT - height)/2.0f;
+ }
+
+ button.frame = CGRectMake(xOrigin,yOrigin,image.image.size.width,height);
+ button.alpha = 0.0f;
+ [button addTarget:self action:selector];
+ NSLog(@"Created the navigation button %@",buttonName);
+ return button;
+}
+
+-(void)addBlackBoxXOrigin:(CGFloat) xOrigin yOrigin:(CGFloat)yOrigin width:(CGFloat) width{
+ self.blackBox =
+ [[MLOSubView alloc]
+ initWithFrame: CGRectMake(xOrigin,
+ yOrigin,
+ width,
+ BLACK_BOX_HEIGHT)
+ color: [UIColor blackColor]
+ cornerRadius: BLACK_BOX_CORNER_RADIUS
+ alpha: 0.0f];
+
+ NSLog(@"Created finder blackbox");
+}
+
+-(void) addLabelXOrigin:(CGFloat) xOrigin yOrigin:(CGFloat) yOrigin{
+ self.label = [[UILabel alloc] initWithFrame:CGRectMake(xOrigin,
+ yOrigin,
+ TEXT_AREA_WIDTH,
+ LABEL_HEIGHT)];
+ _label.textColor=[UIColor whiteColor];
+ _label.backgroundColor = [UIColor clearColor];
+ _label.alpha=0.0f;
+
+ [self updateLabel];
+}
+
+-(void) addTextFieldXOrigin:(CGFloat) xOrigin yOrigin:(CGFloat) yOrigin{
+ self.textField = [[UITextField alloc] initWithFrame:CGRectMake(xOrigin,
+ yOrigin+LABEL_HEIGHT +LABEL_TO_INPUT_FIELD_PADDING,
+ TEXT_AREA_WIDTH,
+ INPUT_FIELD_HEIGHT)];
+ _textField.text =@"";
+ _textField.textColor = [UIColor blackColor];
+ _textField.backgroundColor = [UIColor whiteColor];
+ _textField.alpha = 0.0f;
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(onTextChanged)
+ name:UITextFieldTextDidChangeNotification
+ object:_textField];
+}
+
+
+
+-(void)show{
+ [self fadeTo:FADE_IN_TARGET];
+ [_textField becomeFirstResponder];
+}
+-(void)hide{
+ [self fadeTo:FADE_OUT_TARGET];
+
+ [_textField resignFirstResponder];
+}
+
+-(void)fadeTo:(CGFloat) alphaTarget{
+ if(_blackBox.alpha !=alphaTarget){
+
+ BOOL isFadeNavigationButton = (_selectionCount > 0) || (alphaTarget == 0.0f);
+
+ [UIView animateWithDuration:FADE_DURATION animations:^{
+ _blackBox.alpha = alphaTarget;
+ _label.alpha = alphaTarget;
+ _textField.alpha = alphaTarget;
+
+ if(isFadeNavigationButton){
+ _leftButton.alpha = alphaTarget;
+ _rightButton.alpha = alphaTarget;
+ }
+ }];
+ }
+}
+
+
+-(void)addToMainViewController:(MLOMainViewController *)mainViewController{
+ [mainViewController.canvas addSubview:_blackBox];
+ [mainViewController.canvas addSubview:_label];
+ [mainViewController.canvas addSubview:_textField];
+ [mainViewController.canvas addSubview:_leftButton];
+ [mainViewController.canvas addSubview:_rightButton];
+ self.mainViewController = mainViewController;
+}
+- (void)onTextChanged{
+
+ self.findTime = [NSDate dateWithTimeIntervalSinceNow:FIND_DELAY];
+
+ [self performSelector:@selector(invokeFind) withObject:nil afterDelay:FIND_INVOCATION];
+
+}
+
+-(void) invokeFind{
+
+ if(![[_findTime laterDate:[NSDate date]] isEqualToDate:_findTime]){
+
+ NSInteger trimmedLength = [_textField.text stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]].length;
+
+ if( (_textField.text.length > 0) &&
+ (trimmedLength>0) &&
+ ![_textField.text isEqualToString:_lastSearched]){
+
+ self.lastSearched = [_textField.text copy];
+
+ self.selectionCount = mlo_find(_lastSearched, MARK_FIRST);
+ self.selectedIndex = 0;
+
+ }else if(trimmedLength==0){
+
+ self.lastSearched =@"";
+ self.selectionCount = -1;
+ self.selectedIndex = -1;
+ }
+
+ [self updateLabel];
+ }
+}
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOToolbarButton.h b/ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOToolbarButton.h
new file mode 100644
index 000000000000..2779b0bb172b
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOToolbarButton.h
@@ -0,0 +1,31 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOButton.h"
+
+typedef void (^MLOToolbarButtonCallback)();
+#define MLO_TOOLBAR_BUTTON_STUB_CALLBACK ^{ NSLog(@"stub toolbar button callback");}
+
+
+@class MLOToolbarViewController,MLOResourceImage;
+
+typedef enum { AUTOMATIC, RETAP_OR_OTHER_TAPPED,RETAP_ONLY} MLOToolbarButtonTapReleaseType;
+#define MLOToolbarButtonTapReleaseTypeString(enum) [@[@"AUTOMATIC",@"RETAP_OR_OTHER_TAPPED",@"RETAP_ONLY"] objectAtIndex:enum]
+
+@interface MLOToolbarButton : MLOButton
+@property MLOResourceImage * alternateImage;
+
++(MLOToolbarButton*)buttonWithImage:(MLOResourceImage *) image onTap:(MLOToolbarButtonCallback) onTap tapRelease:(MLOToolbarButtonTapReleaseType)type;
++(MLOToolbarButton*)buttonWithImage:(MLOResourceImage *) image onTap:(MLOToolbarButtonCallback) onTap tapRelease:(MLOToolbarButtonTapReleaseType)type onTapRelease:(MLOToolbarButtonCallback)onTapRelease;
+
+-(void)addToToolbarControler:(MLOToolbarViewController *) toolbar;
+-(void)showLibreOffice;
+-(void)hideLibreOffice;
+-(void)onOtherButtonTapped;
+-(void)switchImage;
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOToolbarButton.m b/ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOToolbarButton.m
new file mode 100644
index 000000000000..1eb0f3c9d253
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOToolbarButton.m
@@ -0,0 +1,157 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOToolbarButton.h"
+#import "MLOToolbarViewController.h"
+#import "MLOToolbarViewController_Impl.h"
+#import "MLOMainViewController.h"
+#import "MLOResourceImage.h"
+
+static const CGFloat
+ TAPPED_ALPHA=1.0f,
+ UNTAPPED_ALPHA=0.3f,
+ BUTTON_IMAGE_X_EDGE_OF_CANVAS_PADDING = 40.0f,
+ BUTTON_IMAGE_Y_EDGE_OF_CANVAS_PADDING = 30.0f,
+ BUTTON_IMAGE_Y_SPACING = 40.0f,
+ BUTTON_THICKENING = 10.f,
+ FADE_TO_UNTAPPED_TIME=0.5f;
+
+static NSInteger toolbarButtonsTotalHeight=BUTTON_IMAGE_Y_EDGE_OF_CANVAS_PADDING;
+
+static const BOOL IS_FLASH_ON_TAP = NO;
+
+@interface MLOToolbarButton ()
+@property MLOToolbarViewController * toolbarController;
+@property (nonatomic,strong) MLOToolbarButtonCallback onTap, onTapRelease;
+@property BOOL isTapped,currentImageIsMain;
+@property MLOToolbarButtonTapReleaseType tapReleaseType;
+@property MLOResourceImage * mainImage;
+@end
+
+
+@implementation MLOToolbarButton
+
+-(void)addToToolbarControler:(MLOToolbarViewController *) toolbar{
+ self.toolbarController = toolbar;
+
+}
++(MLOToolbarButton *)buttonWithImage:(MLOResourceImage *) image onTap:(MLOToolbarButtonCallback) onTap tapRelease:(MLOToolbarButtonTapReleaseType)type{
+ return [MLOToolbarButton buttonWithImage:image onTap:onTap tapRelease:type onTapRelease:MLO_TOOLBAR_BUTTON_STUB_CALLBACK];
+}
++(MLOToolbarButton *)buttonWithImage:(MLOResourceImage *) image onTap:(MLOToolbarButtonCallback) onTap tapRelease:(MLOToolbarButtonTapReleaseType)type onTapRelease:(MLOToolbarButtonCallback)onTapRelease
+{
+
+ MLOToolbarButton * button = [MLOToolbarButton buttonWithType:UIButtonTypeCustom];
+
+ if(button){
+
+ button.mainImage = image;
+ button.onTap = onTap;
+ button.tapReleaseType = type;
+ button.onTapRelease = onTapRelease;
+ button.alternateImage=nil;
+
+ static const CGFloat BUTTON_X=BUTTON_IMAGE_X_EDGE_OF_CANVAS_PADDING -BUTTON_THICKENING,
+ BUTTON_TWICE_THICKENING=2.0f*BUTTON_THICKENING;
+
+ button.frame = CGRectMake(BUTTON_X,
+ toolbarButtonsTotalHeight-BUTTON_THICKENING,
+ image.image.size.width + BUTTON_TWICE_THICKENING,
+ image.image.size.height + BUTTON_TWICE_THICKENING);
+
+ toolbarButtonsTotalHeight += image.image.size.height + BUTTON_IMAGE_Y_SPACING;
+
+ [button reset:0];
+ [button addAction:@selector(onTapAction)];
+
+ }
+ return button;
+}
+
+-(BOOL)isHold{
+ return _tapReleaseType != AUTOMATIC;
+}
+
+-(void)releaseIfNeeded{
+ if(_isTapped && [self isHold]){
+ [self invokeOnTapRelease];
+ }
+ _isTapped = NO;
+}
+
+-(void)reset:(CGFloat) alpha{
+ [self releaseIfNeeded];
+ self.alpha = alpha;
+}
+
+-(void)onOtherButtonTapped{
+ if(_tapReleaseType == RETAP_OR_OTHER_TAPPED){
+ [self releaseIfNeeded];
+ [self fadeToUntapped];
+ }
+}
+
+-(void)invokeOnTapRelease{
+ [self invoke:_onTapRelease named:@"onTapRelease"];
+}
+
+-(void)switchImage{
+ if(_alternateImage!=nil){
+
+ [self setDefaultImage:_currentImageIsMain ? _alternateImage.image : _mainImage.image ];
+ _currentImageIsMain^=YES;
+ }
+}
+- (void) onTapAction{
+ if(_isTapped){
+ if([self isHold]){
+ [self fadeToUntapped];
+ [self invokeOnTapRelease];
+ }
+ }else{
+ _isTapped=YES;
+
+ if(IS_FLASH_ON_TAP){
+ [_toolbarController.mainViewController flash];
+ }
+ self.alpha = TAPPED_ALPHA;
+ if(![self isHold]){
+ [self fadeToUntapped];
+ }
+ [_toolbarController hideAllButtonsBut:self];
+ [self invoke:_onTap named:@"onTap"];
+ }
+}
+
+-(void) fadeToUntapped{
+ if(self.alpha>UNTAPPED_ALPHA){
+
+ [UIView animateWithDuration:FADE_TO_UNTAPPED_TIME animations:^{
+ self.alpha = UNTAPPED_ALPHA;
+ }];
+ }
+
+ _isTapped = NO;
+}
+
+-(void)showLibreOffice{
+ [self setDefaultImage:_mainImage.image];
+ _currentImageIsMain = YES;
+ [self reset:UNTAPPED_ALPHA];
+}
+
+-(void)hideLibreOffice{
+ [self reset: 0];
+}
+
+-(void) invoke:(MLOToolbarButtonCallback) callback named:(NSString *) name{
+ callback();
+ NSLog(@"%@ button perfromed: %@",_mainImage.name, name);
+}
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOToolbarViewController.h b/ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOToolbarViewController.h
new file mode 100644
index 000000000000..74f3fe198b34
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOToolbarViewController.h
@@ -0,0 +1,21 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOViewController.h"
+
+@class MLOMainViewController,MLOToolbarButton;
+@interface MLOToolbarViewController : MLOViewController
+-(id)initWithMainViewController:(MLOMainViewController *) mainViewController;
+-(void)addToMainViewController;
+-(void)showLibreOffice;
+-(void)hideLibreOffice;
+-(void) expandDidToggle;
+-(BOOL) isTappable;
+-(void) onRotate;
+-(void)hideAllButtonsBut:(MLOToolbarButton *) showButton;
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOToolbarViewController.m b/ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOToolbarViewController.m
new file mode 100644
index 000000000000..65b17b19057e
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOToolbarViewController.m
@@ -0,0 +1,136 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOToolbarViewController.h"
+#import "MLOMainViewController.h"
+#import "MLOToolbarButton.h"
+#import "MLOFinder.h"
+#import "MLOToolbarViewController_Impl.h"
+#import "MLOMainViewController_Impl.h"
+#import "MLOResourceImage.h"
+#import "MLOTopbarViewController.h"
+#import "MLOKeyboardManager.h"
+
+@interface MLOToolbarViewController ()
+@property NSArray * buttons;
+@property MLOToolbarButton * expandButton;
+@property MLOFinder * finder;
+@property CGFloat previousHeightOffset;
+@property BOOL tappable;
+@end
+
+@implementation MLOToolbarViewController
+
+-(id)initWithMainViewController:(MLOMainViewController *) mainViewController{
+ self = [self init];
+ if (self) {
+ self.mainViewController = mainViewController;
+ self.buttons=@[[self createExpandButton],
+ [self createFindButton],
+ [self createEditButton]//,
+ //[self createPrintButton],
+ //[self createSaveButton]
+ ];
+ self.tappable = NO;
+
+ _previousHeightOffset=-1.0f;
+
+ }
+ return self;
+}
+
+-(void)addToMainViewController{
+
+ for (MLOToolbarButton * button in _buttons) {
+
+ [button addToToolbarControler:self];
+
+ [_mainViewController.canvas addSubview:button];
+ }
+ [_finder addToMainViewController:_mainViewController];
+}
+
+-(void)showLibreOffice{
+
+ for (MLOToolbarButton * button in _buttons) {
+ [button showLibreOffice];
+ }
+}
+
+-(void)hideAllButtonsBut:(MLOToolbarButton *) showButton{
+ for (MLOToolbarButton * button in _buttons) {
+ if(![button isEqual:showButton]){
+ [button onOtherButtonTapped];
+ }
+ }
+}
+-(BOOL)isTappable{
+ return _tappable;
+}
+-(void)expandDidToggle{
+ [_expandButton switchImage];
+}
+
+-(MLOToolbarButton *)createExpandButton{
+ self.expandButton=
+ [MLOToolbarButton
+ buttonWithImage: [MLOResourceImage expand]
+ onTap: ^{ [self.mainViewController toggleExpand]; }
+ tapRelease: AUTOMATIC];
+
+ _expandButton.alternateImage =[MLOResourceImage shrink];
+
+ return _expandButton;
+}
+-(void) hideLibreOffice{
+ for (MLOToolbarButton * button in _buttons) {
+ [button hideLibreOffice];
+ }
+}
+
+-(MLOToolbarButton *)createFindButton{
+ MLOToolbarButton* findButton=
+ [MLOToolbarButton
+ buttonWithImage: [MLOResourceImage find]
+ onTap: ^{ [self.finder show]; }
+ tapRelease: RETAP_OR_OTHER_TAPPED
+ onTapRelease: ^{ [self.finder hide]; }];
+
+ self.finder = [[MLOFinder alloc] initWithToolbarButton:findButton];
+
+ return findButton;
+}
+
+-(void)onRotate{
+}
+
+-(MLOToolbarButton *)createEditButton{
+ return [MLOToolbarButton
+ buttonWithImage: [MLOResourceImage edit]
+ onTap: ^{ self.tappable =YES; }
+ tapRelease: RETAP_ONLY
+ onTapRelease: ^{ self.tappable = NO;
+ [self.mainViewController.keyboard hide];
+ }];
+}
+
+-(MLOToolbarButton *)createPrintButton{
+ return [MLOToolbarButton
+ buttonWithImage: [MLOResourceImage print]
+ onTap: MLO_TOOLBAR_BUTTON_STUB_CALLBACK
+ tapRelease: RETAP_OR_OTHER_TAPPED];
+}
+
+-(MLOToolbarButton *)createSaveButton{
+ return [MLOToolbarButton
+ buttonWithImage: [MLOResourceImage save]
+ onTap: MLO_TOOLBAR_BUTTON_STUB_CALLBACK
+ tapRelease: RETAP_OR_OTHER_TAPPED];
+}
+
+@end
diff --git a/ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOToolbarViewController_Impl.h b/ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOToolbarViewController_Impl.h
new file mode 100644
index 000000000000..f63c0ff0263f
--- /dev/null
+++ b/ios/shared/ios_sharedlo/objective_c/view_controllers/toolbar/MLOToolbarViewController_Impl.h
@@ -0,0 +1,13 @@
+// -*- Mode: Objective-C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+//
+// This file is part of the LibreOffice project.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#import "MLOToolbarViewController.h"
+
+@interface MLOToolbarViewController ()
+@property MLOMainViewController * mainViewController;
+@end