hoodle-core 0.14 → 0.15
raw patch · 75 files changed
+5535/−4292 lines, 75 filesdep +case-insensitivedep +gtk3dep +handa-gdatadep ~cairodep ~gtkdep ~hoodle-buildersetup-changed
Dependencies added: case-insensitive, gtk3, handa-gdata, hoodle-publish, http-client, http-conduit, http-types, network-uri, persistent, persistent-sqlite, persistent-template, resourcet, websockets
Dependency ranges changed: cairo, gtk, hoodle-builder, hoodle-parser, hoodle-render, hoodle-types, network
Files
- CHANGES +0/−42
- Config.hs +15/−6
- LICENSE +20/−681
- Setup.lhs +1/−1
- csrc/c_initdevice.c +25/−34
- csrc/c_initdevice.h +3/−3
- hoodle-core.cabal +66/−17
- resource/menu.xml +16/−18
- src/Hoodle/Accessor.hs +73/−48
- src/Hoodle/Config.hs +15/−7
- src/Hoodle/Coroutine/Commit.hs +34/−35
- src/Hoodle/Coroutine/ContextMenu.hs +265/−263
- src/Hoodle/Coroutine/Default.hs +207/−362
- src/Hoodle/Coroutine/Default/Menu.hs +239/−0
- src/Hoodle/Coroutine/Dialog.hs +145/−38
- src/Hoodle/Coroutine/Draw.hs +116/−63
- src/Hoodle/Coroutine/Eraser.hs +14/−16
- src/Hoodle/Coroutine/File.hs +329/−245
- src/Hoodle/Coroutine/HandwritingRecognition.hs +32/−33
- src/Hoodle/Coroutine/Highlighter.hs +3/−6
- src/Hoodle/Coroutine/Hub.hs +61/−0
- src/Hoodle/Coroutine/Hub/Common.hs +123/−0
- src/Hoodle/Coroutine/HubInternal.hs +315/−0
- src/Hoodle/Coroutine/HubInternal.hs-boot +67/−0
- src/Hoodle/Coroutine/LaTeX.hs +100/−0
- src/Hoodle/Coroutine/Layer.hs +37/−24
- src/Hoodle/Coroutine/Link.hs +115/−93
- src/Hoodle/Coroutine/Minibuffer.hs +57/−39
- src/Hoodle/Coroutine/Mode.hs +83/−81
- src/Hoodle/Coroutine/Network.hs +62/−63
- src/Hoodle/Coroutine/Page.hs +144/−105
- src/Hoodle/Coroutine/Pen.hs +102/−55
- src/Hoodle/Coroutine/Scroll.hs +50/−49
- src/Hoodle/Coroutine/Select.hs +125/−133
- src/Hoodle/Coroutine/Select/Clipboard.hs +72/−60
- src/Hoodle/Coroutine/Select/ManipulateImage.hs +19/−17
- src/Hoodle/Coroutine/Socket.hs +141/−0
- src/Hoodle/Coroutine/TextInput.hs +176/−184
- src/Hoodle/Coroutine/VerticalSpace.hs +66/−62
- src/Hoodle/Coroutine/Window.hs +159/−75
- src/Hoodle/Device.hsc +10/−8
- src/Hoodle/GUI.hs +93/−84
- src/Hoodle/GUI/Menu.hs +263/−216
- src/Hoodle/GUI/Reflect.hs +158/−135
- src/Hoodle/ModelAction/Adjustment.hs +31/−31
- src/Hoodle/ModelAction/Clipboard.hs +4/−6
- src/Hoodle/ModelAction/ContextMenu.hs +48/−41
- src/Hoodle/ModelAction/File.hs +61/−49
- src/Hoodle/ModelAction/Layer.hs +24/−18
- src/Hoodle/ModelAction/Page.hs +22/−27
- src/Hoodle/ModelAction/Pen.hs +3/−33
- src/Hoodle/ModelAction/Select.hs +25/−42
- src/Hoodle/ModelAction/Text.hs +9/−6
- src/Hoodle/ModelAction/Window.hs +214/−169
- src/Hoodle/Script.hs +7/−3
- src/Hoodle/Script/Coroutine.hs +2/−1
- src/Hoodle/Script/Hook.hs +14/−1
- src/Hoodle/Type/Alias.hs +1/−1
- src/Hoodle/Type/Canvas.hs +28/−46
- src/Hoodle/Type/Coroutine.hs +2/−2
- src/Hoodle/Type/Enum.hs +7/−4
- src/Hoodle/Type/Event.hs +65/−36
- src/Hoodle/Type/HoodleState.hs +254/−152
- src/Hoodle/Type/Hub.hs +28/−0
- src/Hoodle/Type/PageArrangement.hs +1/−1
- src/Hoodle/Type/Synchronization.hs +105/−0
- src/Hoodle/Type/Widget.hs +30/−6
- src/Hoodle/Util.hs +27/−7
- src/Hoodle/View/Coordinate.hs +14/−8
- src/Hoodle/View/Draw.hs +136/−83
- src/Hoodle/Widget/Clock.hs +33/−27
- src/Hoodle/Widget/Dispatch.hs +8/−13
- src/Hoodle/Widget/Layer.hs +39/−35
- src/Hoodle/Widget/PanZoom.hs +41/−43
- src/Hoodle/Widget/Scroll.hs +36/−0
− CHANGES
@@ -1,42 +0,0 @@-0.5: 12 Dec 2011- * First public release. basic pen operation, eraser operation, rectangular selection and file operations are implemented--0.5.1: 16 Dec 2011 - * Use of configuration file '.hxournal'. Enable Use X Input menu. Dependency on xournal-parser and xournal-render is restricted to 0.2.0.* only- * checking gtk+-2.0 using pkg-config--0.6: 18 Dec 2011 - * pdf background support. Annotate PDF menu is activated. preloading pdf background images--0.6.0: 19 Dec 2011 - * some bug fixes (temporary yet) related to automatic scrollbar disappearing. Check when new, open, annotate pdf if xournal file is not saved yet. - -0.6.1: 25 Dec 2011- * undo/redo support, double buffer rendering while scrolling--0.6.2: 15 Jan 2012- * layer support--0.6.3: 24 Jan 2012 - * refine rendering while selection and scrolling. highlighter is implemented. Resizing selected strokes implemented--0.6.4: 6 Feb 2012- * lasso selection, continuous page view. --0.6.5: 12 Feb 2012- * pen button support, pen pressure support, using faster xoj parser --0.6.6: 28 Feb 2012 - * scripting support, zoom in/out implemented. page functions are implemented--==================--0.7: 29 Nov 2012- * change to Hoodle- * new hoodle format - * simplify namespace to Hoodle- * inter-process clipboard support using GtkClipboard- * Image embedding support - * pdf export support --
Config.hs view
@@ -54,12 +54,21 @@ config :: LocalBuildInfo -> IO (Maybe HookedBuildInfo) config bInfo = do - (excode,out,err) <- readProcessWithExitCode "pkg-config" ["--cflags", "gtk+-2.0"] "" - incdirs <- case excode of - ExitSuccess -> return . extractIncDir $ out- _ -> error $ ("failure when running pkg-config --cflags gtk+-2.0 :\n" ++ err) - - + let cflags = (configConfigurationsFlags . configFlags) bInfo+ b = maybe False id (lookup (FlagName "gtk3") cflags)+ incdirs <- if b + then do + (excode,out,err) <- readProcessWithExitCode "pkg-config" ["--cflags", "gtk+-3.0"] "" + case excode of + ExitSuccess -> return . extractIncDir $ out+ _ -> error $ ("failure when running pkg-config --cflags gtk+-3.0 :\n" ++ err) + else do + (excode,out,err) <- readProcessWithExitCode "pkg-config" ["--cflags", "gtk+-2.0"] "" + case excode of + ExitSuccess -> return . extractIncDir $ out+ _ -> error $ ("failure when running pkg-config --cflags gtk+-2.0 :\n" ++ err) ++ let Just lib = library . localPkgDescr $ bInfo buildinfo = libBuildInfo lib let hbi = emptyBuildInfo { extraLibs = extraLibs buildinfo
LICENSE view
@@ -1,686 +1,25 @@-Copyright (C) 2011-2014 Ian-Woo Kim--Hoodle is free software: you can redistribute it and/or modify-it under the terms of the GNU General Public License as published by-the Free Software Foundation, either version 3 of the License, or-(at your option) any later version.--Hoodle is distributed in the hope that it will be useful,-but WITHOUT ANY WARRANTY; without even the implied warranty of-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the-GNU General Public License for more details.-- GNU GENERAL PUBLIC LICENSE- Version 3, 29 June 2007-- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>- Everyone is permitted to copy and distribute verbatim copies- of this license document, but changing it is not allowed.-- Preamble-- The GNU General Public License is a free, copyleft license for-software and other kinds of works.-- The licenses for most software and other practical works are designed-to take away your freedom to share and change the works. By contrast,-the GNU General Public License is intended to guarantee your freedom to-share and change all versions of a program--to make sure it remains free-software for all its users. We, the Free Software Foundation, use the-GNU General Public License for most of our software; it applies also to-any other work released this way by its authors. You can apply it to-your programs, too.-- When we speak of free software, we are referring to freedom, not-price. Our General Public Licenses are designed to make sure that you-have the freedom to distribute copies of free software (and charge for-them if you wish), that you receive source code or can get it if you-want it, that you can change the software or use pieces of it in new-free programs, and that you know you can do these things.-- To protect your rights, we need to prevent others from denying you-these rights or asking you to surrender the rights. Therefore, you have-certain responsibilities if you distribute copies of the software, or if-you modify it: responsibilities to respect the freedom of others.-- For example, if you distribute copies of such a program, whether-gratis or for a fee, you must pass on to the recipients the same-freedoms that you received. You must make sure that they, too, receive-or can get the source code. And you must show them these terms so they-know their rights.-- Developers that use the GNU GPL protect your rights with two steps:-(1) assert copyright on the software, and (2) offer you this License-giving you legal permission to copy, distribute and/or modify it.-- For the developers' and authors' protection, the GPL clearly explains-that there is no warranty for this free software. For both users' and-authors' sake, the GPL requires that modified versions be marked as-changed, so that their problems will not be attributed erroneously to-authors of previous versions.-- Some devices are designed to deny users access to install or run-modified versions of the software inside them, although the manufacturer-can do so. This is fundamentally incompatible with the aim of-protecting users' freedom to change the software. The systematic-pattern of such abuse occurs in the area of products for individuals to-use, which is precisely where it is most unacceptable. Therefore, we-have designed this version of the GPL to prohibit the practice for those-products. If such problems arise substantially in other domains, we-stand ready to extend this provision to those domains in future versions-of the GPL, as needed to protect the freedom of users.-- Finally, every program is threatened constantly by software patents.-States should not allow patents to restrict development and use of-software on general-purpose computers, but in those that do, we wish to-avoid the special danger that patents applied to a free program could-make it effectively proprietary. To prevent this, the GPL assures that-patents cannot be used to render the program non-free.-- The precise terms and conditions for copying, distribution and-modification follow.-- TERMS AND CONDITIONS-- 0. Definitions.-- "This License" refers to version 3 of the GNU General Public License.-- "Copyright" also means copyright-like laws that apply to other kinds of-works, such as semiconductor masks.-- "The Program" refers to any copyrightable work licensed under this-License. Each licensee is addressed as "you". "Licensees" and-"recipients" may be individuals or organizations.-- To "modify" a work means to copy from or adapt all or part of the work-in a fashion requiring copyright permission, other than the making of an-exact copy. The resulting work is called a "modified version" of the-earlier work or a work "based on" the earlier work.-- A "covered work" means either the unmodified Program or a work based-on the Program.-- To "propagate" a work means to do anything with it that, without-permission, would make you directly or secondarily liable for-infringement under applicable copyright law, except executing it on a-computer or modifying a private copy. Propagation includes copying,-distribution (with or without modification), making available to the-public, and in some countries other activities as well.-- To "convey" a work means any kind of propagation that enables other-parties to make or receive copies. Mere interaction with a user through-a computer network, with no transfer of a copy, is not conveying.-- An interactive user interface displays "Appropriate Legal Notices"-to the extent that it includes a convenient and prominently visible-feature that (1) displays an appropriate copyright notice, and (2)-tells the user that there is no warranty for the work (except to the-extent that warranties are provided), that licensees may convey the-work under this License, and how to view a copy of this License. If-the interface presents a list of user commands or options, such as a-menu, a prominent item in the list meets this criterion.-- 1. Source Code.-- The "source code" for a work means the preferred form of the work-for making modifications to it. "Object code" means any non-source-form of a work.-- A "Standard Interface" means an interface that either is an official-standard defined by a recognized standards body, or, in the case of-interfaces specified for a particular programming language, one that-is widely used among developers working in that language.-- The "System Libraries" of an executable work include anything, other-than the work as a whole, that (a) is included in the normal form of-packaging a Major Component, but which is not part of that Major-Component, and (b) serves only to enable use of the work with that-Major Component, or to implement a Standard Interface for which an-implementation is available to the public in source code form. A-"Major Component", in this context, means a major essential component-(kernel, window system, and so on) of the specific operating system-(if any) on which the executable work runs, or a compiler used to-produce the work, or an object code interpreter used to run it.-- The "Corresponding Source" for a work in object code form means all-the source code needed to generate, install, and (for an executable-work) run the object code and to modify the work, including scripts to-control those activities. However, it does not include the work's-System Libraries, or general-purpose tools or generally available free-programs which are used unmodified in performing those activities but-which are not part of the work. For example, Corresponding Source-includes interface definition files associated with source files for-the work, and the source code for shared libraries and dynamically-linked subprograms that the work is specifically designed to require,-such as by intimate data communication or control flow between those-subprograms and other parts of the work.-- The Corresponding Source need not include anything that users-can regenerate automatically from other parts of the Corresponding-Source.-- The Corresponding Source for a work in source code form is that-same work.-- 2. Basic Permissions.-- All rights granted under this License are granted for the term of-copyright on the Program, and are irrevocable provided the stated-conditions are met. This License explicitly affirms your unlimited-permission to run the unmodified Program. The output from running a-covered work is covered by this License only if the output, given its-content, constitutes a covered work. This License acknowledges your-rights of fair use or other equivalent, as provided by copyright law.-- You may make, run and propagate covered works that you do not-convey, without conditions so long as your license otherwise remains-in force. You may convey covered works to others for the sole purpose-of having them make modifications exclusively for you, or provide you-with facilities for running those works, provided that you comply with-the terms of this License in conveying all material for which you do-not control copyright. Those thus making or running the covered works-for you must do so exclusively on your behalf, under your direction-and control, on terms that prohibit them from making any copies of-your copyrighted material outside their relationship with you.-- Conveying under any other circumstances is permitted solely under-the conditions stated below. Sublicensing is not allowed; section 10-makes it unnecessary.-- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.-- No covered work shall be deemed part of an effective technological-measure under any applicable law fulfilling obligations under article-11 of the WIPO copyright treaty adopted on 20 December 1996, or-similar laws prohibiting or restricting circumvention of such-measures.-- When you convey a covered work, you waive any legal power to forbid-circumvention of technological measures to the extent such circumvention-is effected by exercising rights under this License with respect to-the covered work, and you disclaim any intention to limit operation or-modification of the work as a means of enforcing, against the work's-users, your or third parties' legal rights to forbid circumvention of-technological measures.-- 4. Conveying Verbatim Copies.-- You may convey verbatim copies of the Program's source code as you-receive it, in any medium, provided that you conspicuously and-appropriately publish on each copy an appropriate copyright notice;-keep intact all notices stating that this License and any-non-permissive terms added in accord with section 7 apply to the code;-keep intact all notices of the absence of any warranty; and give all-recipients a copy of this License along with the Program.-- You may charge any price or no price for each copy that you convey,-and you may offer support or warranty protection for a fee.-- 5. Conveying Modified Source Versions.-- You may convey a work based on the Program, or the modifications to-produce it from the Program, in the form of source code under the-terms of section 4, provided that you also meet all of these conditions:-- a) The work must carry prominent notices stating that you modified- it, and giving a relevant date.-- b) The work must carry prominent notices stating that it is- released under this License and any conditions added under section- 7. This requirement modifies the requirement in section 4 to- "keep intact all notices".-- c) You must license the entire work, as a whole, under this- License to anyone who comes into possession of a copy. This- License will therefore apply, along with any applicable section 7- additional terms, to the whole of the work, and all its parts,- regardless of how they are packaged. This License gives no- permission to license the work in any other way, but it does not- invalidate such permission if you have separately received it.-- d) If the work has interactive user interfaces, each must display- Appropriate Legal Notices; however, if the Program has interactive- interfaces that do not display Appropriate Legal Notices, your- work need not make them do so.-- A compilation of a covered work with other separate and independent-works, which are not by their nature extensions of the covered work,-and which are not combined with it such as to form a larger program,-in or on a volume of a storage or distribution medium, is called an-"aggregate" if the compilation and its resulting copyright are not-used to limit the access or legal rights of the compilation's users-beyond what the individual works permit. Inclusion of a covered work-in an aggregate does not cause this License to apply to the other-parts of the aggregate.-- 6. Conveying Non-Source Forms.-- You may convey a covered work in object code form under the terms-of sections 4 and 5, provided that you also convey the-machine-readable Corresponding Source under the terms of this License,-in one of these ways:-- a) Convey the object code in, or embodied in, a physical product- (including a physical distribution medium), accompanied by the- Corresponding Source fixed on a durable physical medium- customarily used for software interchange.-- b) Convey the object code in, or embodied in, a physical product- (including a physical distribution medium), accompanied by a- written offer, valid for at least three years and valid for as- long as you offer spare parts or customer support for that product- model, to give anyone who possesses the object code either (1) a- copy of the Corresponding Source for all the software in the- product that is covered by this License, on a durable physical- medium customarily used for software interchange, for a price no- more than your reasonable cost of physically performing this- conveying of source, or (2) access to copy the- Corresponding Source from a network server at no charge.-- c) Convey individual copies of the object code with a copy of the- written offer to provide the Corresponding Source. This- alternative is allowed only occasionally and noncommercially, and- only if you received the object code with such an offer, in accord- with subsection 6b.-- d) Convey the object code by offering access from a designated- place (gratis or for a charge), and offer equivalent access to the- Corresponding Source in the same way through the same place at no- further charge. You need not require recipients to copy the- Corresponding Source along with the object code. If the place to- copy the object code is a network server, the Corresponding Source- may be on a different server (operated by you or a third party)- that supports equivalent copying facilities, provided you maintain- clear directions next to the object code saying where to find the- Corresponding Source. Regardless of what server hosts the- Corresponding Source, you remain obligated to ensure that it is- available for as long as needed to satisfy these requirements.-- e) Convey the object code using peer-to-peer transmission, provided- you inform other peers where the object code and Corresponding- Source of the work are being offered to the general public at no- charge under subsection 6d.-- A separable portion of the object code, whose source code is excluded-from the Corresponding Source as a System Library, need not be-included in conveying the object code work.-- A "User Product" is either (1) a "consumer product", which means any-tangible personal property which is normally used for personal, family,-or household purposes, or (2) anything designed or sold for incorporation-into a dwelling. In determining whether a product is a consumer product,-doubtful cases shall be resolved in favor of coverage. For a particular-product received by a particular user, "normally used" refers to a-typical or common use of that class of product, regardless of the status-of the particular user or of the way in which the particular user-actually uses, or expects or is expected to use, the product. A product-is a consumer product regardless of whether the product has substantial-commercial, industrial or non-consumer uses, unless such uses represent-the only significant mode of use of the product.-- "Installation Information" for a User Product means any methods,-procedures, authorization keys, or other information required to install-and execute modified versions of a covered work in that User Product from-a modified version of its Corresponding Source. The information must-suffice to ensure that the continued functioning of the modified object-code is in no case prevented or interfered with solely because-modification has been made.-- If you convey an object code work under this section in, or with, or-specifically for use in, a User Product, and the conveying occurs as-part of a transaction in which the right of possession and use of the-User Product is transferred to the recipient in perpetuity or for a-fixed term (regardless of how the transaction is characterized), the-Corresponding Source conveyed under this section must be accompanied-by the Installation Information. But this requirement does not apply-if neither you nor any third party retains the ability to install-modified object code on the User Product (for example, the work has-been installed in ROM).-- The requirement to provide Installation Information does not include a-requirement to continue to provide support service, warranty, or updates-for a work that has been modified or installed by the recipient, or for-the User Product in which it has been modified or installed. Access to a-network may be denied when the modification itself materially and-adversely affects the operation of the network or violates the rules and-protocols for communication across the network.-- Corresponding Source conveyed, and Installation Information provided,-in accord with this section must be in a format that is publicly-documented (and with an implementation available to the public in-source code form), and must require no special password or key for-unpacking, reading or copying.-- 7. Additional Terms.-- "Additional permissions" are terms that supplement the terms of this-License by making exceptions from one or more of its conditions.-Additional permissions that are applicable to the entire Program shall-be treated as though they were included in this License, to the extent-that they are valid under applicable law. If additional permissions-apply only to part of the Program, that part may be used separately-under those permissions, but the entire Program remains governed by-this License without regard to the additional permissions.-- When you convey a copy of a covered work, you may at your option-remove any additional permissions from that copy, or from any part of-it. (Additional permissions may be written to require their own-removal in certain cases when you modify the work.) You may place-additional permissions on material, added by you to a covered work,-for which you have or can give appropriate copyright permission.-- Notwithstanding any other provision of this License, for material you-add to a covered work, you may (if authorized by the copyright holders of-that material) supplement the terms of this License with terms:-- a) Disclaiming warranty or limiting liability differently from the- terms of sections 15 and 16 of this License; or-- b) Requiring preservation of specified reasonable legal notices or- author attributions in that material or in the Appropriate Legal- Notices displayed by works containing it; or-- c) Prohibiting misrepresentation of the origin of that material, or- requiring that modified versions of such material be marked in- reasonable ways as different from the original version; or-- d) Limiting the use for publicity purposes of names of licensors or- authors of the material; or-- e) Declining to grant rights under trademark law for use of some- trade names, trademarks, or service marks; or-- f) Requiring indemnification of licensors and authors of that- material by anyone who conveys the material (or modified versions of- it) with contractual assumptions of liability to the recipient, for- any liability that these contractual assumptions directly impose on- those licensors and authors.-- All other non-permissive additional terms are considered "further-restrictions" within the meaning of section 10. If the Program as you-received it, or any part of it, contains a notice stating that it is-governed by this License along with a term that is a further-restriction, you may remove that term. If a license document contains-a further restriction but permits relicensing or conveying under this-License, you may add to a covered work material governed by the terms-of that license document, provided that the further restriction does-not survive such relicensing or conveying.-- If you add terms to a covered work in accord with this section, you-must place, in the relevant source files, a statement of the-additional terms that apply to those files, or a notice indicating-where to find the applicable terms.-- Additional terms, permissive or non-permissive, may be stated in the-form of a separately written license, or stated as exceptions;-the above requirements apply either way.-- 8. Termination.-- You may not propagate or modify a covered work except as expressly-provided under this License. Any attempt otherwise to propagate or-modify it is void, and will automatically terminate your rights under-this License (including any patent licenses granted under the third-paragraph of section 11).-- However, if you cease all violation of this License, then your-license from a particular copyright holder is reinstated (a)-provisionally, unless and until the copyright holder explicitly and-finally terminates your license, and (b) permanently, if the copyright-holder fails to notify you of the violation by some reasonable means-prior to 60 days after the cessation.-- Moreover, your license from a particular copyright holder is-reinstated permanently if the copyright holder notifies you of the-violation by some reasonable means, this is the first time you have-received notice of violation of this License (for any work) from that-copyright holder, and you cure the violation prior to 30 days after-your receipt of the notice.-- Termination of your rights under this section does not terminate the-licenses of parties who have received copies or rights from you under-this License. If your rights have been terminated and not permanently-reinstated, you do not qualify to receive new licenses for the same-material under section 10.-- 9. Acceptance Not Required for Having Copies.-- You are not required to accept this License in order to receive or-run a copy of the Program. Ancillary propagation of a covered work-occurring solely as a consequence of using peer-to-peer transmission-to receive a copy likewise does not require acceptance. However,-nothing other than this License grants you permission to propagate or-modify any covered work. These actions infringe copyright if you do-not accept this License. Therefore, by modifying or propagating a-covered work, you indicate your acceptance of this License to do so.-- 10. Automatic Licensing of Downstream Recipients.-- Each time you convey a covered work, the recipient automatically-receives a license from the original licensors, to run, modify and-propagate that work, subject to this License. You are not responsible-for enforcing compliance by third parties with this License.-- An "entity transaction" is a transaction transferring control of an-organization, or substantially all assets of one, or subdividing an-organization, or merging organizations. If propagation of a covered-work results from an entity transaction, each party to that-transaction who receives a copy of the work also receives whatever-licenses to the work the party's predecessor in interest had or could-give under the previous paragraph, plus a right to possession of the-Corresponding Source of the work from the predecessor in interest, if-the predecessor has it or can get it with reasonable efforts.-- You may not impose any further restrictions on the exercise of the-rights granted or affirmed under this License. For example, you may-not impose a license fee, royalty, or other charge for exercise of-rights granted under this License, and you may not initiate litigation-(including a cross-claim or counterclaim in a lawsuit) alleging that-any patent claim is infringed by making, using, selling, offering for-sale, or importing the Program or any portion of it.-- 11. Patents.-- A "contributor" is a copyright holder who authorizes use under this-License of the Program or a work on which the Program is based. The-work thus licensed is called the contributor's "contributor version".-- A contributor's "essential patent claims" are all patent claims-owned or controlled by the contributor, whether already acquired or-hereafter acquired, that would be infringed by some manner, permitted-by this License, of making, using, or selling its contributor version,-but do not include claims that would be infringed only as a-consequence of further modification of the contributor version. For-purposes of this definition, "control" includes the right to grant-patent sublicenses in a manner consistent with the requirements of-this License.-- Each contributor grants you a non-exclusive, worldwide, royalty-free-patent license under the contributor's essential patent claims, to-make, use, sell, offer for sale, import and otherwise run, modify and-propagate the contents of its contributor version.-- In the following three paragraphs, a "patent license" is any express-agreement or commitment, however denominated, not to enforce a patent-(such as an express permission to practice a patent or covenant not to-sue for patent infringement). To "grant" such a patent license to a-party means to make such an agreement or commitment not to enforce a-patent against the party.-- If you convey a covered work, knowingly relying on a patent license,-and the Corresponding Source of the work is not available for anyone-to copy, free of charge and under the terms of this License, through a-publicly available network server or other readily accessible means,-then you must either (1) cause the Corresponding Source to be so-available, or (2) arrange to deprive yourself of the benefit of the-patent license for this particular work, or (3) arrange, in a manner-consistent with the requirements of this License, to extend the patent-license to downstream recipients. "Knowingly relying" means you have-actual knowledge that, but for the patent license, your conveying the-covered work in a country, or your recipient's use of the covered work-in a country, would infringe one or more identifiable patents in that-country that you have reason to believe are valid.-- If, pursuant to or in connection with a single transaction or-arrangement, you convey, or propagate by procuring conveyance of, a-covered work, and grant a patent license to some of the parties-receiving the covered work authorizing them to use, propagate, modify-or convey a specific copy of the covered work, then the patent license-you grant is automatically extended to all recipients of the covered-work and works based on it.-- A patent license is "discriminatory" if it does not include within-the scope of its coverage, prohibits the exercise of, or is-conditioned on the non-exercise of one or more of the rights that are-specifically granted under this License. You may not convey a covered-work if you are a party to an arrangement with a third party that is-in the business of distributing software, under which you make payment-to the third party based on the extent of your activity of conveying-the work, and under which the third party grants, to any of the-parties who would receive the covered work from you, a discriminatory-patent license (a) in connection with copies of the covered work-conveyed by you (or copies made from those copies), or (b) primarily-for and in connection with specific products or compilations that-contain the covered work, unless you entered into that arrangement,-or that patent license was granted, prior to 28 March 2007.-- Nothing in this License shall be construed as excluding or limiting-any implied license or other defenses to infringement that may-otherwise be available to you under applicable patent law.-- 12. No Surrender of Others' Freedom.-- If conditions are imposed on you (whether by court order, agreement or-otherwise) that contradict the conditions of this License, they do not-excuse you from the conditions of this License. If you cannot convey a-covered work so as to satisfy simultaneously your obligations under this-License and any other pertinent obligations, then as a consequence you may-not convey it at all. For example, if you agree to terms that obligate you-to collect a royalty for further conveying from those to whom you convey-the Program, the only way you could satisfy both those terms and this-License would be to refrain entirely from conveying the Program.-- 13. Use with the GNU Affero General Public License.-- Notwithstanding any other provision of this License, you have-permission to link or combine any covered work with a work licensed-under version 3 of the GNU Affero General Public License into a single-combined work, and to convey the resulting work. The terms of this-License will continue to apply to the part which is the covered work,-but the special requirements of the GNU Affero General Public License,-section 13, concerning interaction through a network will apply to the-combination as such.-- 14. Revised Versions of this License.-- The Free Software Foundation may publish revised and/or new versions of-the GNU General Public License from time to time. Such new versions will-be similar in spirit to the present version, but may differ in detail to-address new problems or concerns.-- Each version is given a distinguishing version number. If the-Program specifies that a certain numbered version of the GNU General-Public License "or any later version" applies to it, you have the-option of following the terms and conditions either of that numbered-version or of any later version published by the Free Software-Foundation. If the Program does not specify a version number of the-GNU General Public License, you may choose any version ever published-by the Free Software Foundation.-- If the Program specifies that a proxy can decide which future-versions of the GNU General Public License can be used, that proxy's-public statement of acceptance of a version permanently authorizes you-to choose that version for the Program.-- Later license versions may give you additional or different-permissions. However, no additional obligations are imposed on any-author or copyright holder as a result of your choosing to follow a-later version.-- 15. Disclaimer of Warranty.-- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM-IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.-- 16. Limitation of Liability.-- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF-SUCH DAMAGES.-- 17. Interpretation of Sections 15 and 16.-- If the disclaimer of warranty and limitation of liability provided-above cannot be given local legal effect according to their terms,-reviewing courts shall apply local law that most closely approximates-an absolute waiver of all civil liability in connection with the-Program, unless a warranty or assumption of liability accompanies a-copy of the Program in return for a fee.-- END OF TERMS AND CONDITIONS-- How to Apply These Terms to Your New Programs-- If you develop a new program, and you want it to be of the greatest-possible use to the public, the best way to achieve this is to make it-free software which everyone can redistribute and change under these terms.-- To do so, attach the following notices to the program. It is safest-to attach them to the start of each source file to most effectively-state the exclusion of warranty; and each file should have at least-the "copyright" line and a pointer to where the full notice is found.-- <one line to give the program's name and a brief idea of what it does.>- Copyright (C) <year> <name of author>-- This program is free software: you can redistribute it and/or modify- it under the terms of the GNU General Public License as published by- the Free Software Foundation, either version 3 of the License, or- (at your option) any later version.-- This program is distributed in the hope that it will be useful,- but WITHOUT ANY WARRANTY; without even the implied warranty of- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the- GNU General Public License for more details.-- You should have received a copy of the GNU General Public License- along with this program. If not, see <http://www.gnu.org/licenses/>.--Also add information on how to contact you by electronic and paper mail.+The following license covers this documentation, and the source code, except+where otherwise indicated. - If the program does terminal interaction, make it output a short-notice like this when it starts in an interactive mode:+Copyright 2011-2014, Ian-Woo Kim. All rights reserved. - <program> Copyright (C) <year> <name of author>- This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.- This is free software, and you are welcome to redistribute it- under certain conditions; type `show c' for details.+Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met: -The hypothetical commands `show w' and `show c' should show the appropriate-parts of the General Public License. Of course, your program's commands-might be different; for a GUI interface, you would use an "about box".+* Redistributions of source code must retain the above copyright notice, this+ list of conditions and the following disclaimer. - You should also get your employer (if you work as a programmer) or school,-if any, to sign a "copyright disclaimer" for the program, if necessary.-For more information on this, and how to apply and follow the GNU GPL, see-<http://www.gnu.org/licenses/>.+* Redistributions in binary form must reproduce the above copyright notice,+ this list of conditions and the following disclaimer in the documentation+ and/or other materials provided with the distribution. - The GNU General Public License does not permit incorporating your program-into proprietary programs. If your program is a subroutine library, you-may consider it more useful to permit linking proprietary applications with-the library. If this is what you want to do, use the GNU Lesser General-Public License instead of this License. But first, please read-<http://www.gnu.org/philosophy/why-not-lgpl.html>.+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY EXPRESS OR+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO+EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Setup.lhs view
@@ -6,4 +6,4 @@ > > main :: IO () > main = defaultMainWithHooks myConfigHook-> +> -- main = defaultMain
csrc/c_initdevice.c view
@@ -2,9 +2,11 @@ #include <stdio.h> #include <string.h> -+#ifndef GTK3 #include "XInput.h"+#endif // GTK3 +#ifndef GTK3 // // Globals. //@@ -115,6 +117,7 @@ } + void find_wacom( char* stylus_name, char* eraser_name) { Display *display = XOpenDisplay(NULL); @@ -136,8 +139,7 @@ } return ; }--+#endif // not GTK3 void initdevice ( int* core , int* stylus@@ -149,53 +151,54 @@ , char* touchname ) {- // xinput_start(); - printf("initdevice : stylusname = %s\n", stylusname ); printf("initdevice : erasername = %s\n", erasername ); printf("initdevice : touchname = %s\n", touchname ); GList* dev_list; GdkDevice* device;+#ifdef GTK3+ GdkDisplay* disp = gdk_display_get_default();+ GdkDeviceManager *devman = gdk_display_get_device_manager(disp);++ dev_list = gdk_device_manager_list_devices(devman, GDK_DEVICE_TYPE_SLAVE );+#else // GTK3 dev_list = gdk_devices_list();+#endif // GTK3 (*stylus) = 0; while (dev_list != NULL) {- // printf ("one device\n"); device = (GdkDevice *)dev_list->data;- // printf(" %d : %s \n", device, device->name );- if (device != gdk_device_get_core_pointer()) {- // #ifdef ENABLE_XINPUT_BUGFIX+ // device = GPOINTER_TO_INT(dev_list->data);+ if ( gdk_device_get_source(device) != GDK_SOURCE_MOUSE ) { gdk_device_set_axis_use(device, 0, GDK_AXIS_IGNORE); gdk_device_set_axis_use(device, 1, GDK_AXIS_IGNORE);- // #endif gdk_device_set_mode(device, GDK_MODE_SCREEN); - // printf("This is xinput device %s \n", device -> name);- if( !strcmp (device->name, stylusname) ) {- // printf("got stylus\n"); + if( !strcmp (gdk_device_get_name(device), stylusname) ) { (*stylus) = (int) device; } - if( !strcmp (device->name, erasername) ) { - // printf("got eraser\n");+ if( !strcmp (gdk_device_get_name(device), erasername) ) { (*eraser) = (int) device; } - if( !strcmp (device->name, touchname) ) { - // printf("got eraser\n");+ if( !strcmp (gdk_device_get_name(device), touchname) ) { (*touch) = (int) device; } } else { - if( !strcmp (device->name, corepointername) ) { - // printf("got Core Pointer\n"); + if( !strcmp (gdk_device_get_name(device), corepointername) ) { (*core) = (int) device; } } - dev_list = dev_list->next; +#ifdef GTK3+ dev_list = g_list_next(dev_list); +#else // GTK3+ dev_list = dev_list->next;+#endif // GTK3 } } -+#ifndef GTK3 void enable_touch( char* touch_name ) { printf("enable touch: %s\n", touch_name ) ; @@ -204,18 +207,6 @@ void disable_touch( GdkDrawable *gdkwin, char* touch_name ) { printf("disable touch: %s\n", touch_name ); - /* Display *dpy = XOpenDisplay(NULL); - XIEventMask eventmask ; - Window win = GDK_DRAWABLE_XID(gdkwin) ; - unsigned char mask[1] = { 0 } ; -- eventmask.deviceid = 12 ; - eventmask.make_len = sizeof(mask); - eventmask.mask = mask ; - - XISelectEvents (dpy,win,&eventmask,1); -- XCloseDisplay(dpy); */ }-+#endif // GTK3
csrc/c_initdevice.h view
@@ -1,11 +1,11 @@ #include <gtk/gtk.h> #include <stdio.h> -void find_wacom( char* stylus_name, char* eraser_name ) ; +// void find_wacom( char* stylus_name, char* eraser_name ) ; void initdevice( int* core, int* stylus, int* eraser, char* corepointername, char* stylusname, char* erasername ); -void enable_touch( char* touch_name ) ;+// void enable_touch( char* touch_name ) ; -void disable_touch( char* touch_name ); +// void disable_touch( char* touch_name );
hoodle-core.cabal view
@@ -1,11 +1,11 @@ Name: hoodle-core-Version: 0.14+Version: 0.15 Synopsis: Core library for hoodle Description: Hoodle is a pen notetaking program written in haskell. hoodle-core is the core library written in haskell and using gtk2hs Homepage: http://ianwookim.org/hoodle-License: GPL-3+License: BSD3 License-file: LICENSE Author: Ian-Woo Kim Maintainer: Ian-Woo Kim <ianwookim@gmail.com>@@ -16,15 +16,27 @@ data-files: template/*.html.st resource/*.png resource/*.xml- CHANGES Config.hs Source-repository head type: git location: http://www.github.com/wavewave/hoodle-core ++Flag Dyre+ Description: dynamic reconfiguration support+ Default: False++Flag Gtk3+ Description: compile with gtk3+ Default: False ++Flag Hub+ Description: communication with Hub+ Default: False+ Library hs-source-dirs: src- ghc-options: -Wall -funbox-strict-fields -fno-warn-unused-do-bind -fno-warn-orphans + ghc-options: -Wall -funbox-strict-fields -fno-warn-unused-do-bind -fno-warn-orphans ghc-prof-options: -caf-all -auto-all Build-Depends: aeson>=0.7,@@ -35,31 +47,30 @@ base64-bytestring >= 0.1, binary, bytestring >= 0.9, - cairo > 0.12,+ cairo > 0.13,+ case-insensitive, cereal >= 0.3.5, containers >= 0.4, configurator >= 0.2, coroutine-object >= 0.2, - dbus >= 0.10, Diff >= 0.3, directory > 1,- dyre >= 0.8.11, either >= 3.1, errors >= 1.3, filepath > 1, fsnotify >= 0.0.7, gd >= 3000.7, - gtk > 0.12, - hoodle-builder >= 0.3,- hoodle-parser >= 0.3,- hoodle-render >= 0.4,- hoodle-types >= 0.3,+ handa-gdata >= 0.6.9.3, + hoodle-builder >= 0.3.0,+ hoodle-parser >= 0.3.0,+ hoodle-publish >= 0.2,+ hoodle-render == 0.5.*,+ hoodle-types >= 0.3.0,+ http-types, lens >= 2.5, monad-loops >= 0.3, mtl > 2,- network, - network-info, - network-simple >= 0.3,+ network-uri > 2.6, old-locale >= 1.0, pango > 0.12, poppler >= 0.12.2.2, @@ -77,7 +88,29 @@ unordered-containers >= 0.2, uuid >= 1.2.7, vector >= 0.10,+ websockets, xournal-parser >= 0.5.0.2+ --+ if flag(dyre)+ Build-depends: dyre >= 0.8.11+ -- + if flag(gtk3) + Build-depends: gtk3 > 0.13 + else + Build-depends: gtk > 0.13+ -- + if flag(hub)+ Build-depends: + dbus >= 0.10, + http-client,+ http-conduit,+ network > 2.6, + network-info, + network-simple >= 0.3,+ persistent,+ persistent-sqlite,+ persistent-template,+ resourcet Exposed-Modules: Hoodle.Accessor@@ -86,6 +119,7 @@ Hoodle.Coroutine.Commit Hoodle.Coroutine.ContextMenu Hoodle.Coroutine.Default+ Hoodle.Coroutine.Default.Menu Hoodle.Coroutine.Dialog Hoodle.Coroutine.Draw Hoodle.Coroutine.Eraser@@ -96,7 +130,6 @@ Hoodle.Coroutine.Link Hoodle.Coroutine.Minibuffer Hoodle.Coroutine.Mode- Hoodle.Coroutine.Network Hoodle.Coroutine.Page Hoodle.Coroutine.Pen Hoodle.Coroutine.Scroll@@ -104,6 +137,7 @@ Hoodle.Coroutine.Select.Clipboard Hoodle.Coroutine.Select.ManipulateImage Hoodle.Coroutine.TextInput+ Hoodle.Coroutine.LaTeX Hoodle.Coroutine.VerticalSpace Hoodle.Coroutine.Window Hoodle.Device@@ -145,6 +179,15 @@ Hoodle.Widget.Dispatch Hoodle.Widget.Layer Hoodle.Widget.PanZoom+ Hoodle.Widget.Scroll+ if flag(hub)+ Exposed-Modules: Hoodle.Coroutine.Hub+ Hoodle.Coroutine.Hub.Common+ Hoodle.Coroutine.HubInternal+ Hoodle.Coroutine.Network+ Hoodle.Coroutine.Socket+ Hoodle.Type.Hub+ Hoodle.Type.Synchronization Other-Modules: Paths_hoodle_core c-sources: @@ -154,5 +197,11 @@ csrc/c_initdevice.h csrc/template-hsc-gtk2hs.h csrc/XInput.h- cc-options: -Wno-pointer-to-int-cast -std=gnu99 -DDEBUG + cc-options: -fPIC -Wno-pointer-to-int-cast -std=gnu99 -DDEBUG extra-libraries: X11 Xi dl pthread+ if flag(dyre)+ cpp-options: -DDYRE+ if flag(gtk3)+ cpp-options: -DGTK3+ if flag(hub)+ cpp-options: -DHUB
@@ -28,6 +28,7 @@ </menu> <menu action="VMA"> <menuitem action="TOGPANZOOMA" />+ <menuitem action="TOGSCRA" /> <menu action="ZOOMA" > <menuitem action="ZMINA" /> <menuitem action="ZMOUTA" /> @@ -64,6 +65,7 @@ <menu action="IMA"> <menuitem action="LDIMGA" /> <menuitem action="LDSVGA" />+ <menuitem action="LDIMGBKGA" /> <menuitem action="LDPREIMGA" /> <menuitem action="LDPREIMG2A" /> <menuitem action="LDPREIMG3A" />@@ -73,11 +75,13 @@ <menuitem action="EDITSRCA" /> <menuitem action="EDITNETSRCA" /> <menuitem action="TEXTFROMSRCA" />+ <menuitem action="TOGGLENETSRCA" /> <separator /> <menuitem action="LATEXA" /> <menuitem action="LATEXNETA" /> <menuitem action="COMBINELATEXA" /> <menuitem action="LATEXFROMSRCA" />+ <menuitem action="UPDATELATEXA" /> <separator /> </menu> <menu action="PMA">@@ -157,7 +161,7 @@ <menu action="OMA"> <menuitem action="UXINPUTA" /> <menuitem action="HANDA" />- <menuitem action="SMTHSCRA" />+ <!-- <menuitem action="SMTHSCRA" /> --> <menuitem action="POPMENUA" /> <menuitem action="EBDIMGA" /> <menuitem action="EBDPDFA" />@@ -165,24 +169,18 @@ <menuitem action="KEEPRATIOA" /> <menuitem action="VCURSORA" /> <menuitem action="TOGCLOCKA" />- <menuitem action="DCRDCOREA" /> - <menuitem action="ERSRTIPA" /> - <menuitem action="PRESSRSENSA" /> - <menuitem action="PGHILTA" /> - <menuitem action="MLTPGVWA" /> - <menuitem action="MLTPGA" /> - <menuitem action="BTN2MAPA" /> - <menuitem action="BTN3MAPA" /> - <separator />- <menuitem action="ANTIALIASBMPA" />- <menuitem action="PRGRSBKGA" /> - <menuitem action="PRNTPPRULEA" /> - <menuitem action="LFTHNDSCRBRA" /> - <menuitem action="SHRTNMENUA" /> - <separator />- <menuitem action="AUTOSAVEPREFA" />- <menuitem action="SAVEPREFA" />+ <menuitem action="PRESSRSENSA" />+ <menu action="NEWPAGEMODEA">+ <menuitem action="NEWPAGEPLAINA" />+ <menuitem action="NEWPAGELASTA" />+ <menuitem action="NEWPAGECYCLEA" />+ </menu> <menuitem action="RELAUNCHA" />+ <menuitem action="HUBA" />+ </menu>+ <menu action="WMA">+ <menuitem action="ADDTABA" />+ <menuitem action="CLOSETABA" /> </menu> <menu action="HMA"> <menuitem action="ABOUTA" />
src/Hoodle/Accessor.hs view
@@ -1,11 +1,15 @@-{-# LANGUAGE TypeOperators, GADTs, ScopedTypeVariables, Rank2Types #-}+-- {-# LANGUAGE TypeOperators #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE Rank2Types #-} ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Accessor -- Copyright : (c) 2011-2014 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -15,20 +19,21 @@ module Hoodle.Accessor where import Control.Applicative-import Control.Lens (Simple,Lens,view,set)+import Control.Concurrent.STM (readTVarIO)+import Control.Lens (Simple,Lens,view,set,(.~)) import Control.Monad hiding (mapM_, forM_)+import Control.Monad.IO.Class import qualified Control.Monad.State as St hiding (mapM_, forM_)-import Control.Monad.Trans import Data.Foldable import qualified Data.IntMap as M-import Graphics.UI.Gtk hiding (get,set)+import qualified Data.Text as T+import qualified Data.Text.Encoding as TE+import qualified Graphics.UI.Gtk as Gtk -- from hoodle-platform import Data.Hoodle.Generic import Data.Hoodle.Select import Graphics.Hoodle.Render.Type -- from this package--- import Hoodle.GUI.Menu--- import Hoodle.GUI.Reflect import Hoodle.ModelAction.Layer import Hoodle.Type import Hoodle.Type.Alias@@ -41,6 +46,20 @@ updateXState :: (HoodleState -> MainCoroutine HoodleState) -> MainCoroutine () updateXState action = St.put =<< action =<< St.get +-- | update unitHoodle+updateUhdl :: (UnitHoodle -> MainCoroutine UnitHoodle) -> MainCoroutine ()+updateUhdl action = do xst <- St.get+ let uhdl = view (unitHoodles.currentUnit) xst+ uhdl' <- action uhdl+ St.put (set (unitHoodles.currentUnit) uhdl' xst)++-- | update unitHoodle+pureUpdateUhdl :: (UnitHoodle -> UnitHoodle) -> MainCoroutine ()+pureUpdateUhdl func = do xst <- St.get+ let uhdl = (func . view (unitHoodles.currentUnit)) xst+ St.put ((unitHoodles.currentUnit .~ uhdl) xst)++ -- | getPenType :: MainCoroutine PenType getPenType = view (penInfo.penType) <$> St.get@@ -49,16 +68,18 @@ getCurrentPageCurr :: MainCoroutine (Page EditMode) getCurrentPageCurr = do xstate <- St.get - let hdlmodst = view hoodleModeState xstate- cinfobox = view currentCanvasInfo xstate + let uhdl = view (unitHoodles.currentUnit) xstate+ hdlmodst = view hoodleModeState uhdl+ cinfobox = view currentCanvasInfo uhdl return $ forBoth' unboxBiAct (flip getCurrentPageFromHoodleModeState hdlmodst) cinfobox -- | getCurrentPageCvsId :: CanvasId -> MainCoroutine (Page EditMode) getCurrentPageCvsId cid = do xstate <- St.get - let hdlmodst = view hoodleModeState xstate- cinfobox = getCanvasInfo cid xstate + let uhdl = view (unitHoodles.currentUnit) xstate+ hdlmodst = view hoodleModeState uhdl+ cinfobox = getCanvasInfo cid uhdl return $ forBoth' unboxBiAct (flip getCurrentPageFromHoodleModeState hdlmodst) cinfobox @@ -82,22 +103,22 @@ rItmsInCurrLyr = return . view gitems . getCurrentLayer =<< getCurrentPageCurr -- |-otherCanvas :: HoodleState -> [Int] -otherCanvas = M.keys . getCanvasInfoMap +otherCanvas :: UnitHoodle -> [Int] +otherCanvas = M.keys . view cvsInfoMap -- | apply an action to all canvases applyActionToAllCVS :: (CanvasId -> MainCoroutine ()) -> MainCoroutine () applyActionToAllCVS action = do xstate <- St.get - let cinfoMap = getCanvasInfoMap xstate+ let cinfoMap = view (unitHoodles.currentUnit.cvsInfoMap) xstate keys = M.keys cinfoMap forM_ keys action -- | -getCanvasGeometryCvsId :: CanvasId -> HoodleState -> IO CanvasGeometry -getCanvasGeometryCvsId cid xstate = do - let cinfobox = getCanvasInfo cid xstate+getCanvasGeometryCvsId :: CanvasId -> UnitHoodle -> IO CanvasGeometry +getCanvasGeometryCvsId cid uhdl = do + let cinfobox = getCanvasInfo cid uhdl cpn = PageNum . view (unboxLens currentPageNum) $ cinfobox canvas = view (unboxLens drawArea) cinfobox fsingle :: CanvasInfo a -> IO CanvasGeometry @@ -106,9 +127,9 @@ forBoth' unboxBiAct fsingle cinfobox -- |-getGeometry4CurrCvs :: HoodleState -> IO CanvasGeometry -getGeometry4CurrCvs xstate = do - let cinfobox = view currentCanvasInfo xstate+getGeometry4CurrCvs :: UnitHoodle -> IO CanvasGeometry +getGeometry4CurrCvs uhdl = do + let cinfobox = view currentCanvasInfo uhdl cpn = PageNum . view (unboxLens currentPageNum) $ cinfobox canvas = view (unboxLens drawArea) cinfobox fsingle :: CanvasInfo a -> IO CanvasGeometry @@ -116,41 +137,45 @@ . view (viewInfo.pageArrangement) forBoth' unboxBiAct fsingle cinfobox - --- | update flag in HoodleState when corresponding toggle UI changed -updateFlagFromToggleUI :: String -- ^ UI toggle button id- -> Simple Lens HoodleState Bool -- ^ lens for flag - -> MainCoroutine Bool-updateFlagFromToggleUI toggleid lensforflag = do - xstate <- St.get - let ui = view gtkUIManager xstate - agr <- liftIO ( uiManagerGetActionGroups ui >>= \x ->- case x of - [] -> error "No action group? "- y:_ -> return y )- togglea <- liftIO (actionGroupGetAction agr toggleid) - >>= maybe (error "updateFlagFromToggleUI") - (return . castToToggleAction)- b <- liftIO $ toggleActionGetActive togglea- St.modify (set lensforflag b) - return b + + -- | set toggle UI button to the corresponding HoodleState -setToggleUIForFlag :: String - -> Simple Lens HoodleState Bool -- ^ lens for flag- -> HoodleState - -> IO Bool -setToggleUIForFlag toggleid lensforflag xstate = do +lensSetToggleUIForFlag :: String + -> Simple Lens HoodleState Bool -- ^ lens for flag+ -> HoodleState + -> IO Bool +lensSetToggleUIForFlag toggleid lensforflag xstate =+ let b = view lensforflag xstate in setToggleUIForFlag toggleid b xstate++-- | set toggle UI button to the corresponding HoodleState +setToggleUIForFlag :: String -> Bool -> HoodleState -> IO Bool +setToggleUIForFlag toggleid b xstate = do let ui = view gtkUIManager xstate - b = view lensforflag xstate - agr <- uiManagerGetActionGroups ui >>= \x ->+ agr <- Gtk.uiManagerGetActionGroups ui >>= \x -> case x of [] -> error "No action group? " y:_ -> return y - togglea <- actionGroupGetAction agr toggleid >>= \(Just x) -> - return (castToToggleAction x) - toggleActionSetActive togglea b+ togglea <- Gtk.actionGroupGetAction agr toggleid >>= \(Just x) -> + return (Gtk.castToToggleAction x) + Gtk.toggleActionSetActive togglea b return b +-- |+renderCache :: MainCoroutine RenderCache+renderCache = (view renderCacheVar <$> St.get) >>= liftIO . readTVarIO +-- |+getHoodleFilePath :: UnitHoodle -> Maybe FilePath +getHoodleFilePath = fileStore2Maybe . view (hoodleFileControl.hoodleFileName) ++-- |+fileStore2Maybe :: FileStore -> Maybe FilePath +fileStore2Maybe (LocalDir Nothing) = Nothing+fileStore2Maybe (LocalDir (Just filename)) = Just filename+fileStore2Maybe (TempDir filename) = Just filename++-- |+getHoodleID :: UnitHoodle -> T.Text+getHoodleID = TE.decodeUtf8 . view ghoodleID . getHoodle
src/Hoodle/Config.hs view
@@ -3,7 +3,7 @@ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Config --- Copyright : (c) 2011-2013 Ian-Woo Kim+-- Copyright : (c) 2011-2014 Ian-Woo Kim -- -- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>@@ -62,17 +62,25 @@ (mpanzoom :: Maybe String) <- C.lookup c "PanZoomWidget" (mlayer :: Maybe String) <- C.lookup c "LayerWidget" - let panzoom = maybe True (parse "PanZoomWidget") mpanzoom - layer = maybe True (parse "LayerWidget") mlayer+ let panzoom = maybe True (parseBool "PanZoomWidget") mpanzoom + layer = maybe True (parseBool "LayerWidget") mlayer print ("WidgetConfig =" ++ show (panzoom,layer) ) return (panzoom,layer)- where parse msg str = case str of- "true" -> True- "false" -> False - _ -> error ("cannot understand " ++ msg ++ " in configfile") +parseBool :: String -> String -> Bool+parseBool msg str = case str of+ "true" -> True+ "false" -> False + _ -> error ("cannot understand " ++ msg ++ " in configfile")+ +getPenConfig :: Config -> IO Bool+getPenConfig c = do+ (mvcursor :: Maybe String) <- C.lookup c "variablecursor"+ let vcursor = maybe False (parseBool "variablecursor") mvcursor+ return vcursor+ {- getNetworkInfo :: Config -> IO (Maybe HoodleClipClientConfiguration)
src/Hoodle/Coroutine/Commit.hs view
@@ -1,7 +1,7 @@ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Coroutine.Commit --- Copyright : (c) 2011-2014 Ian-Woo Kim+-- Copyright : (c) 2011-2015 Ian-Woo Kim -- -- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>@@ -12,74 +12,73 @@ module Hoodle.Coroutine.Commit where -import Control.Lens (view,set)+import Control.Lens (view,set,(.~)) import Control.Monad.Trans import Control.Monad.State -- from this package+import Hoodle.Accessor import Hoodle.Coroutine.Draw -import Hoodle.ModelAction.File+import Hoodle.GUI.Reflect import Hoodle.ModelAction.Page import Hoodle.Type.Coroutine import Hoodle.Type.HoodleState -import Hoodle.Type.Undo +import Hoodle.Type.Undo+import Hoodle.Util -- | save state and add the current status in undo history - commit :: HoodleState -> MainCoroutine () commit xstate = do + put xstate let ui = view gtkUIManager xstate- liftIO $ toggleSave ui True- let hdlmodst = view hoodleModeState xstate- undotable = view undoTable xstate - undotable' = addToUndo undotable hdlmodst- xstate' = set isSaved False - . set undoTable undotable'- $ xstate- put xstate' + liftIO $ reflectUIToggle ui "SAVEA" True+ pureUpdateUhdl $ \uhdl -> + let hdlmodst = view hoodleModeState uhdl+ undotable = view undoTable uhdl+ undotable' = addToUndo undotable hdlmodst+ in ((isSaved .~ False) . (undoTable .~ undotable')) uhdl -- | - commit_ :: MainCoroutine () commit_ = get >>= commit -- | - undo :: MainCoroutine () undo = do xstate <- get- let utable = view undoTable xstate- cache = view renderCache xstate+ let uhdl = view (unitHoodles.currentUnit) xstate+ let utable = view undoTable uhdl case getPrevUndo utable of - Nothing -> liftIO $ putStrLn "no undo item yet"- Just (hdlmodst1,newtable) -> do - hdlmodst <- liftIO $ resetHoodleModeStateBuffers cache hdlmodst1 - put . set hoodleModeState hdlmodst- . set undoTable newtable - =<< (liftIO (updatePageAll hdlmodst xstate))+ Nothing -> msgShout "no undo item yet"+ Just (hdlmodst,newtable) -> do + let cid = getCurrentCanvasId uhdl+ callRenderer_ $ resetHoodleModeStateBuffers cid hdlmodst+ updateUhdl $ \uhdl' -> do+ uhdl'' <- liftIO (updatePageAll hdlmodst uhdl')+ return $ ( (hoodleModeState .~ hdlmodst) . (undoTable .~ newtable)) uhdl'' invalidateAll -- | - redo :: MainCoroutine () redo = do xstate <- get- let utable = view undoTable xstate- cache = view renderCache xstate+ let uhdl = view (unitHoodles.currentUnit) xstate+ utable = view undoTable uhdl+ cid = getCurrentCanvasId uhdl case getNextUndo utable of - Nothing -> liftIO $ putStrLn "no redo item"- Just (hdlmodst1,newtable) -> do - hdlmodst <- liftIO $ resetHoodleModeStateBuffers cache hdlmodst1- put . set hoodleModeState hdlmodst- . set undoTable newtable - =<< (liftIO (updatePageAll hdlmodst xstate))+ Nothing -> msgShout "no redo item"+ Just (hdlmodst,newtable) -> do + callRenderer_ $ resetHoodleModeStateBuffers cid hdlmodst+ updateUhdl $ \uhdl' -> do + uhdl'' <- liftIO (updatePageAll hdlmodst uhdl')+ let uhdl''' = ( set hoodleModeState hdlmodst+ . set undoTable newtable ) uhdl'' + return uhdl''' invalidateAll -- | clearUndoHistory :: MainCoroutine () -clearUndoHistory = do - xstate <- get- put . set undoTable (emptyUndo 1) $ xstate+clearUndoHistory = pureUpdateUhdl (undoTable .~ (emptyUndo 1))
src/Hoodle/Coroutine/ContextMenu.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-}@@ -5,9 +6,9 @@ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Coroutine.ContextMenu--- Copyright : (c) 2011-2014 Ian-Woo Kim+-- Copyright : (c) 2011-2015 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -18,7 +19,8 @@ -- from other packages import Control.Applicative-import Control.Lens (view,set,(%~),(^.))+import Control.Concurrent.STM (readTVarIO)+import Control.Lens (view,set,(^.),(.~)) import Control.Monad.State hiding (mapM_,forM_) import Control.Monad.Trans.Maybe import qualified Data.ByteString.Char8 as B@@ -31,14 +33,11 @@ import qualified Data.Text as T (unpack, splitAt) import qualified Data.Text.Encoding as TE import qualified Graphics.Rendering.Cairo as Cairo--- import qualified Graphics.Rendering.Cairo.SVG as RSVG-import Graphics.UI.Gtk hiding (get,set)+import qualified Graphics.UI.Gtk as Gtk import System.Directory import System.FilePath import System.Process -- from hoodle-platform-import Control.Monad.Trans.Crtn.Event-import Control.Monad.Trans.Crtn.Queue import Data.Hoodle.BBox import Data.Hoodle.Generic import Data.Hoodle.Select@@ -79,29 +78,27 @@ processContextMenu :: ContextMenuEvent -> MainCoroutine () processContextMenu (CMenuSaveSelectionAs ityp) = do - xst <- get- forM_ (getSelectedItmsFromHoodleState xst) - (\hititms-> - let ulbbox = (unUnion . mconcat . fmap (Union . Middle . getBBox)) hititms - in case ulbbox of - Middle bbox -> - case ityp of - TypSVG -> exportCurrentSelectionAsSVG hititms bbox- TypPDF -> exportCurrentSelectionAsPDF hititms bbox- _ -> return () - )+ mhititms <- getSelectedItmsFromUnitHoodle . view (unitHoodles.currentUnit) <$> get+ forM_ mhititms $ \hititms-> + let ulbbox = (unUnion . mconcat . fmap (Union . Middle . getBBox)) hititms + in case ulbbox of + Middle bbox -> + case ityp of + TypSVG -> exportCurrentSelectionAsSVG hititms bbox+ TypPDF -> exportCurrentSelectionAsPDF hititms bbox+ _ -> return () processContextMenu CMenuCut = cutSelection processContextMenu CMenuCopy = copySelection processContextMenu CMenuDelete = deleteSelection processContextMenu (CMenuCanvasView cid pnum _x _y) = do - xstate <- get - let cmap = xstate ^. cvsInfoMap - let mcinfobox = IM.lookup cid cmap + uhdl <- view (unitHoodles.currentUnit) <$> get + let cmap = uhdl ^. cvsInfoMap + mcinfobox = IM.lookup cid cmap case mcinfobox of - Nothing -> liftIO $ putStrLn "error in processContextMenu"+ Nothing -> msgShout "error in processContextMenu" Just _cinfobox -> do - cinfobox' <- liftIO (setPage xstate pnum cid)- put $ set cvsInfoMap (IM.adjust (const cinfobox') cid cmap) xstate + cinfobox' <- liftIO (setPage uhdl pnum cid)+ pureUpdateUhdl (cvsInfoMap .~ IM.adjust (const cinfobox') cid cmap) adjustScrollbarWithGeometryCvsId cid invalidateAll processContextMenu (CMenuRotate dir imgbbx) = rotateImage dir imgbbx@@ -113,12 +110,11 @@ hset <- xst ^. hookSet customAutosavePage hset <*> pure pg processContextMenu (CMenuLinkConvert nlnk) = - either (const (return ())) action - . hoodleModeStateEither - . (^. hoodleModeState) =<< get + either_ action . hoodleModeStateEither . (^. hoodleModeState) . view (unitHoodles.currentUnit) =<< get where action thdl = do xst <- get - let cache = xst ^. renderCache+ let uhdl = view (unitHoodles.currentUnit) xst+ cid = getCurrentCanvasId uhdl case thdl ^. gselSelected of Nothing -> return () Just (n,tpg) -> do @@ -135,48 +131,51 @@ layer' = GLayer buf . TEitherAlterHitted . Right $ alist' return (set (glayers.selectedLayer) layer' tpg) Right _ -> error "processContextMenu: activelayer"- nthdl <- liftIO $ updateTempHoodleSelectIO cache thdl ntpg n- commit . set hoodleModeState (SelectState nthdl)- =<< (liftIO (updatePageAll (SelectState nthdl) xst))+ nthdl <- updateTempHoodleSelectM cid thdl ntpg n+ uhdl' <- liftIO $ updatePageAll (SelectState nthdl) uhdl+ commit $ (unitHoodles.currentUnit .~ uhdl') xst invalidateAll processContextMenu CMenuCreateALink = - fileChooser FileChooserActionOpen Nothing >>= mapM_ linkSelectionWithFile+ fileChooser Gtk.FileChooserActionOpen Nothing >>= mapM_ linkSelectionWithFile processContextMenu CMenuAssocWithNewFile = do xst <- get let msuggestedact = xst ^. hookSet >>= fileNameSuggestionHook (msuggested :: Maybe String) <- maybe (return Nothing) (liftM Just . liftIO) msuggestedact - fileChooser FileChooserActionSave msuggested >>= + fileChooser Gtk.FileChooserActionSave msuggested >>= mapM_ (\fp -> do b <- liftIO (doesFileExist fp) if b then okMessageBox "The file already exist!" else do - let action = mkIOaction $ \_ -> do - nhdl <- liftIO $ defaultHoodle - (L.writeFile fp . builder) nhdl - createProcess (proc "hoodle" [fp]) - return (UsrEv ActionOrdered)- modify (tempQueue %~ enqueue action) - waitSomeEvent (\x -> case x of ActionOrdered -> True ; _ -> False)+ doIOaction_ $ do + nhdl <- liftIO $ defaultHoodle + (L.writeFile fp . builder) nhdl + createProcess (proc "hoodle" [fp]) linkSelectionWithFile fp return () ) processContextMenu (CMenuMakeLinkToAnchor anc) = do xst <- get uuidbstr <- liftIO $ B.pack . show <$> nextRandom- docidbstr <- view ghoodleID . getHoodle <$> get- let mloc = view (hoodleFileControl.hoodleFileName) xst+ let uhdl = view (unitHoodles.currentUnit) xst + docidbstr = (view ghoodleID . getHoodle) uhdl+ mloc = case view (hoodleFileControl.hoodleFileName) uhdl of+ LocalDir Nothing -> Nothing+ LocalDir (Just fp) -> Just fp+ TempDir _ -> Nothing loc = maybe "" B.pack mloc- let lnk = LinkAnchor uuidbstr docidbstr loc (anchor_id anc) "" (0,0) (Dim 50 50)+ lnk = LinkAnchor uuidbstr docidbstr loc (anchor_id anc) "" (0,0) (Dim 50 50) callRenderer $ cnstrctRItem (ItemLink lnk) >>= return . GotRItem RenderEv (GotRItem newitem) <- waitSomeEvent (\case RenderEv (GotRItem _) -> True; _ -> False) insertItemAt Nothing newitem processContextMenu (CMenuPangoConvert (x0,y0) txt) = textInput (Just (x0,y0)) txt processContextMenu (CMenuLaTeXConvert (x0,y0) txt) = laTeXInput (Just (x0,y0)) txt+#ifdef HUB processContextMenu (CMenuLaTeXConvertNetwork (x0,y0) txt) = laTeXInputNetwork (Just (x0,y0)) txt-processContextMenu (CMenuLaTeXUpdate (x0,y0) key) = runMaybeT (laTeXInputKeyword (x0,y0) key) >> return ()+#endif+processContextMenu (CMenuLaTeXUpdate (x0,y0) dim key) = runMaybeT (laTeXInputKeyword (x0,y0) (Just dim) key) >> return () processContextMenu (CMenuCropImage imgbbox) = cropImage imgbbox processContextMenu (CMenuExportHoodlet itm) = do res <- handwritingRecognitionDialog@@ -192,15 +191,15 @@ let fp = hoodletdir </> str <.> "hdlt" L.writeFile fp (Hoodlet.builder itm) processContextMenu (CMenuConvertSelection itm) = do- xstate <- get - let pgnum = view (currentCanvasInfo . unboxLens currentPageNum) xstate + uhdl <- view (unitHoodles.currentUnit) <$> get + let pgnum = view (currentCanvasInfo . unboxLens currentPageNum) uhdl deleteSelection callRenderer $ return . GotRItem =<< cnstrctRItem itm RenderEv (GotRItem newitem) <- waitSomeEvent (\case RenderEv (GotRItem _) -> True; _ -> False) let BBox (x0,y0) _ = getBBox newitem insertItemAt (Just (PageNum pgnum, PageCoord (x0,y0))) newitem processContextMenu CMenuCustom = do- either (const (return ())) action . hoodleModeStateEither . view hoodleModeState =<< get + either_ action . hoodleModeStateEither . view hoodleModeState . view (unitHoodles.currentUnit) =<< get where action thdl = do xst <- get forM_ (view gselSelected thdl) @@ -213,27 +212,28 @@ -- | linkSelectionWithFile :: FilePath -> MainCoroutine () linkSelectionWithFile fname = do- liftM getSelectedItmsFromHoodleState get >>= - mapM_ (\hititms -> - let ulbbox = (unUnion . mconcat . fmap (Union . Middle . getBBox)) hititms - in case ulbbox of - Middle bbox -> do - cache <- view renderCache <$> get - svg <- liftIO $ makeSVGFromSelection cache hititms bbox- uuid <- liftIO $ nextRandom- let uuidbstr = B.pack (show uuid) - deleteSelection - linkInsert "simple" (uuidbstr,fname) fname (svg_render svg,bbox) - _ -> return () )+ uhdl <- view (unitHoodles.currentUnit) <$> get+ let cid = getCurrentCanvasId uhdl+ forM_ (getSelectedItmsFromUnitHoodle uhdl) $ \hititms -> + let ulbbox = (unUnion . mconcat . fmap (Union . Middle . getBBox)) hititms + in case ulbbox of + Middle bbox -> do + cache <- renderCache+ svg <- liftIO $ makeSVGFromSelection cache cid hititms bbox+ uuid <- liftIO $ nextRandom+ let uuidbstr = B.pack (show uuid) + deleteSelection + linkInsert "simple" (uuidbstr,fname) fname (svg_render svg,bbox)+ _ -> return () -- | exportCurrentSelectionAsSVG :: [RItem] -> BBox -> MainCoroutine () exportCurrentSelectionAsSVG hititms bbox@(BBox (ulx,uly) (lrx,lry)) = - fileChooser FileChooserActionSave Nothing >>= maybe (return ()) action + fileChooser Gtk.FileChooserActionSave Nothing >>= mapM_ action where action filename = do- cache <- view renderCache <$> get+ (cache,cid) <- (,) <$> renderCache <*> (getCurrentCanvasId . view (unitHoodles.currentUnit) <$> get) -- this is rather temporary not to make mistake if takeExtension filename /= ".svg" then fileExtensionInvalid (".svg","export") @@ -242,15 +242,15 @@ liftIO $ Cairo.withSVGSurface filename (lrx-ulx) (lry-uly) $ \s -> Cairo.renderWith s $ do Cairo.translate (-ulx) (-uly)- mapM_ (renderRItem cache) hititms+ mapM_ (renderRItem cache cid) hititms exportCurrentSelectionAsPDF :: [RItem] -> BBox -> MainCoroutine () exportCurrentSelectionAsPDF hititms bbox@(BBox (ulx,uly) (lrx,lry)) = - fileChooser FileChooserActionSave Nothing >>= maybe (return ()) action + fileChooser Gtk.FileChooserActionSave Nothing >>= mapM_ action where action filename = do- cache <- view renderCache <$> get+ (cache,cid) <- (,) <$> renderCache <*> (getCurrentCanvasId . view (unitHoodles.currentUnit) <$> get) -- this is rather temporary not to make mistake if takeExtension filename /= ".pdf" then fileExtensionInvalid (".svg","export") @@ -259,7 +259,7 @@ liftIO $ Cairo.withPDFSurface filename (lrx-ulx) (lry-uly) $ \s -> Cairo.renderWith s $ do Cairo.translate (-ulx) (-uly)- mapM_ (renderRItem cache) hititms+ mapM_ (renderRItem cache cid) hititms -- | exportImage :: S.Image -> MainCoroutine ()@@ -267,7 +267,7 @@ runMaybeT $ do pngbstr <- (MaybeT . return . getByteStringIfEmbeddedPNG . S.img_src) img- fp <- MaybeT (fileChooser FileChooserActionSave Nothing) + fp <- MaybeT (fileChooser Gtk.FileChooserActionSave Nothing) liftIO $ B.writeFile fp pngbstr return () @@ -276,216 +276,218 @@ showContextMenu (pnum,(x,y)) = do xstate <- get when (view (settings.doesUsePopUpMenu) xstate) $ do - let cids = IM.keys . view cvsInfoMap $ xstate- cid = fst . view currentCanvas $ xstate - mselitms = do lst <- getSelectedItmsFromHoodleState xstate+ let uhdl = view (unitHoodles.currentUnit) xstate+ cids = IM.keys . view cvsInfoMap $ uhdl+ cid = fst . view currentCanvas $ uhdl + mselitms = do lst <- getSelectedItmsFromUnitHoodle uhdl if null lst then Nothing else Just lst - modify (tempQueue %~ enqueue (action xstate mselitms cid cids)) + doIOaction (action xstate mselitms cid cids) >> waitSomeEvent (\e->case e of ContextMenuCreated -> True ; _ -> False) >> return () where - action xstate msitms cid cids - = Left . ActionOrder $ \evhandler -> do - menu <- menuNew - menuSetTitle menu "MyMenu"- case msitms of - Nothing -> return ()- Just sitms -> do - menuitem1 <- menuItemNewWithLabel "Make SVG"- menuitem2 <- menuItemNewWithLabel "Make PDF"- menuitem3 <- menuItemNewWithLabel "Cut"- menuitem4 <- menuItemNewWithLabel "Copy"- menuitem5 <- menuItemNewWithLabel "Delete"- menuitem6 <- menuItemNewWithLabel "New File Linked Here"- menuitem1 `on` menuItemActivate $ - evhandler (UsrEv (GotContextMenuSignal (CMenuSaveSelectionAs TypSVG)))- menuitem2 `on` menuItemActivate $ - evhandler (UsrEv (GotContextMenuSignal (CMenuSaveSelectionAs TypPDF)))- menuitem3 `on` menuItemActivate $ - evhandler (UsrEv (GotContextMenuSignal (CMenuCut)))- menuitem4 `on` menuItemActivate $ - evhandler (UsrEv (GotContextMenuSignal (CMenuCopy)))- menuitem5 `on` menuItemActivate $ - evhandler (UsrEv (GotContextMenuSignal (CMenuDelete)))- menuitem6 `on` menuItemActivate $ - evhandler (UsrEv (GotContextMenuSignal (CMenuAssocWithNewFile)))- menuAttach menu menuitem1 0 1 1 2 - menuAttach menu menuitem2 0 1 2 3- menuAttach menu menuitem3 1 2 0 1 - menuAttach menu menuitem4 1 2 1 2 - menuAttach menu menuitem5 1 2 2 3 - menuAttach menu menuitem6 1 2 3 4 - mapM_ (\mi -> menuAttach menu mi 1 2 5 6) =<< menuCreateALink evhandler sitms - case sitms of - sitm : [] -> do - menuhdlt <- menuItemNewWithLabel "Make Hoodlet"- menuhdlt `on` menuItemActivate $ - ( evhandler . UsrEv . GotContextMenuSignal - . CMenuExportHoodlet . rItem2Item ) sitm- menuAttach menu menuhdlt 0 1 8 9- - case sitm of - RItemLink lnkbbx _msfc -> do - let lnk = bbxed_content lnkbbx- forM_ ((urlParse . B.unpack . link_location) lnk)- (\urlpath -> do milnk <- menuOpenALink urlpath- menuAttach menu milnk 0 1 3 4 )- case lnk of - Link _i _typ _lstr _txt _cmd _rdr _pos _dim -> - convertLinkFromSimpleToDocID lnk >>= - mapM_ (\link -> do - let LinkDocID _ uuid _ _ _ _ _ _ = link - menuitemcvt <- menuItemNewWithLabel ("Convert Link With ID" ++ show uuid) - menuitemcvt `on` menuItemActivate $- ( evhandler - . UsrEv - . GotContextMenuSignal - . CMenuLinkConvert ) link- menuAttach menu menuitemcvt 0 1 4 5 - ) - LinkDocID i lid file txt cmd rdr pos dim -> do - runMaybeT $ do - hset <- (MaybeT . return . view hookSet) xstate- f <- (MaybeT . return . lookupPathFromId) hset- file' <- MaybeT (f (B.unpack lid))- guard ((B.unpack file) /= file')- let link = LinkDocID - i lid (B.pack file') txt cmd rdr pos dim- menuitemcvt <- liftIO $ menuItemNewWithLabel - ("Correct Path to " ++ show file') - liftIO (menuitemcvt `on` menuItemActivate $ - ( evhandler - . UsrEv - . GotContextMenuSignal - . CMenuLinkConvert ) link)- liftIO $ menuAttach menu menuitemcvt 0 1 4 5 - return ()- LinkAnchor i lid file aid bstr pos dim -> do - runMaybeT $ do - hset <- (MaybeT . return . view hookSet) xstate- f <- (MaybeT . return . lookupPathFromId) hset- file' <- MaybeT (f (B.unpack lid))- guard ((B.unpack file) /= file')- let link = LinkAnchor i lid (B.pack file') aid bstr pos dim- menuitemcvt <- liftIO $ menuItemNewWithLabel - ("Correct Path to " ++ show file') - liftIO (menuitemcvt `on` menuItemActivate $ - ( evhandler - . UsrEv - . GotContextMenuSignal - . CMenuLinkConvert) link)- liftIO $ menuAttach menu menuitemcvt 0 1 4 5 - return ()-- RItemSVG svgbbx _msfc -> do- let svg = bbxed_content svgbbx- BBox (x0,y0) _ = getBBox svgbbx- forM_ ((,) <$> svg_text svg <*> svg_command svg) $ \(btxt,cmd) -> do- let txt = TE.decodeUtf8 btxt- case cmd of - "pango" -> do - menuitemedt <- menuItemNewWithLabel ("Edit Text") - menuitemedt `on` menuItemActivate $ do - evhandler (UsrEv (GotContextMenuSignal (CMenuPangoConvert (x0,y0) txt)))- menuAttach menu menuitemedt 0 1 4 5- return ()- "latex" -> do - menuitemedt <- menuItemNewWithLabel ("Edit LaTeX")- menuitemedt `on` menuItemActivate $ do- evhandler (UsrEv (GotContextMenuSignal (CMenuLaTeXConvert (x0,y0) txt)))- menuAttach menu menuitemedt 0 1 4 5 - --- menuitemnet <- menuItemNewWithLabel ("Edit LaTeX Network")- menuitemnet `on` menuItemActivate $ do- evhandler (UsrEv (GotContextMenuSignal (CMenuLaTeXConvertNetwork (x0,y0) txt)))- menuAttach menu menuitemnet 0 1 5 6- return ()- -- - let (txth,txtt) = T.splitAt 19 txt - when ( txth == "embedlatex:keyword:" ) $ do- menuitemup <- menuItemNewWithLabel ("Update LaTeX")- menuitemup `on` menuItemActivate $ do- evhandler (UsrEv (GotContextMenuSignal (CMenuLaTeXUpdate (x0,y0) txtt)))- menuAttach menu menuitemup 0 1 6 7- return ()+ action xstate msitms cid cids evhandler = do + menu <- Gtk.menuNew + Gtk.menuSetTitle menu ("MyMenu" :: String)+ case msitms of + Nothing -> return ()+ Just sitms -> do + menuitem1 <- Gtk.menuItemNewWithLabel ("Make SVG" :: String)+ menuitem2 <- Gtk.menuItemNewWithLabel ("Make PDF" :: String)+ menuitem3 <- Gtk.menuItemNewWithLabel ("Cut" :: String)+ menuitem4 <- Gtk.menuItemNewWithLabel ("Copy" :: String)+ menuitem5 <- Gtk.menuItemNewWithLabel ("Delete" :: String)+ menuitem6 <- Gtk.menuItemNewWithLabel ("New File Linked Here" :: String)+ menuitem1 `Gtk.on` Gtk.menuItemActivate $ + evhandler (UsrEv (GotContextMenuSignal (CMenuSaveSelectionAs TypSVG)))+ menuitem2 `Gtk.on` Gtk.menuItemActivate $ + evhandler (UsrEv (GotContextMenuSignal (CMenuSaveSelectionAs TypPDF)))+ menuitem3 `Gtk.on` Gtk.menuItemActivate $ + evhandler (UsrEv (GotContextMenuSignal (CMenuCut)))+ menuitem4 `Gtk.on` Gtk.menuItemActivate $ + evhandler (UsrEv (GotContextMenuSignal (CMenuCopy)))+ menuitem5 `Gtk.on` Gtk.menuItemActivate $ + evhandler (UsrEv (GotContextMenuSignal (CMenuDelete)))+ menuitem6 `Gtk.on` Gtk.menuItemActivate $ + evhandler (UsrEv (GotContextMenuSignal (CMenuAssocWithNewFile)))+ Gtk.menuAttach menu menuitem1 0 1 1 2 + Gtk.menuAttach menu menuitem2 0 1 2 3+ Gtk.menuAttach menu menuitem3 1 2 0 1 + Gtk.menuAttach menu menuitem4 1 2 1 2 + Gtk.menuAttach menu menuitem5 1 2 2 3 + Gtk.menuAttach menu menuitem6 1 2 3 4 + mapM_ (\mi -> Gtk.menuAttach menu mi 1 2 5 6) =<< menuCreateALink evhandler sitms + case sitms of + sitm : [] -> do + menuhdlt <- Gtk.menuItemNewWithLabel ("Make Hoodlet" :: String)+ menuhdlt `Gtk.on` Gtk.menuItemActivate $ + ( evhandler . UsrEv . GotContextMenuSignal + . CMenuExportHoodlet . rItem2Item ) sitm+ Gtk.menuAttach menu menuhdlt 0 1 8 9 - _ -> return ()- RItemImage imgbbx _msfc -> do- menuitemcrop <- menuItemNewWithLabel ("Crop Image") - menuitemcrop `on` menuItemActivate $ do - (evhandler . UsrEv . GotContextMenuSignal . CMenuCropImage) imgbbx- menuitemrotcw <- menuItemNewWithLabel ("Rotate Image CW") - menuitemrotcw `on` menuItemActivate $ do - (evhandler . UsrEv . GotContextMenuSignal) (CMenuRotate CW imgbbx)- menuitemrotccw <- menuItemNewWithLabel ("Rotate Image CCW") - menuitemrotccw `on` menuItemActivate $ do - (evhandler . UsrEv . GotContextMenuSignal) (CMenuRotate CCW imgbbx)- menuitemexport <- menuItemNewWithLabel ("Export Image")- menuitemexport `on` menuItemActivate $ do- (evhandler . UsrEv . GotContextMenuSignal) (CMenuExport imgbbx)- -- - menuAttach menu menuitemcrop 0 1 4 5- menuAttach menu menuitemrotcw 0 1 5 6- menuAttach menu menuitemrotccw 0 1 6 7- menuAttach menu menuitemexport 0 1 7 8- -- + case sitm of + RItemLink lnkbbx _msfc -> do + let lnk = bbxed_content lnkbbx+ forM_ ((urlParse . B.unpack . link_location) lnk)+ (\urlpath -> do milnk <- menuOpenALink evhandler urlpath+ Gtk.menuAttach menu milnk 0 1 3 4 )+ case lnk of + Link _i _typ _lstr _txt _cmd _rdr _pos _dim -> + convertLinkFromSimpleToDocID lnk >>= + mapM_ (\link -> do + let LinkDocID _ uuid _ _ _ _ _ _ = link + menuitemcvt <- Gtk.menuItemNewWithLabel ("Convert Link With ID" ++ show uuid :: String) + menuitemcvt `Gtk.on` Gtk.menuItemActivate $+ ( evhandler + . UsrEv + . GotContextMenuSignal + . CMenuLinkConvert ) link+ Gtk.menuAttach menu menuitemcvt 0 1 4 5 + ) + LinkDocID i lid file txt cmd rdr pos dim -> do + runMaybeT $ do + hset <- (MaybeT . return . view hookSet) xstate+ f <- (MaybeT . return . lookupPathFromId) hset+ file' <- MaybeT (f (B.unpack lid))+ guard ((B.unpack file) /= file')+ let link = LinkDocID + i lid (B.pack file') txt cmd rdr pos dim+ menuitemcvt <- liftIO $ Gtk.menuItemNewWithLabel + ("Correct Path to " ++ show file' :: String) + liftIO (menuitemcvt `Gtk.on` Gtk.menuItemActivate $ + ( evhandler + . UsrEv + . GotContextMenuSignal + . CMenuLinkConvert ) link)+ liftIO $ Gtk.menuAttach menu menuitemcvt 0 1 4 5 return ()- RItemAnchor ancbbx _ -> do- menuitemmklnk <- menuItemNewWithLabel ("Link to this anchor")- menuitemmklnk `on` menuItemActivate $- ( evhandler - . UsrEv - . GotContextMenuSignal - . CMenuMakeLinkToAnchor - . bbxed_content) ancbbx- menuAttach menu menuitemmklnk 0 1 4 5 - _ -> return ()+ LinkAnchor i lid file aid bstr pos dim -> do + runMaybeT $ do + hset <- (MaybeT . return . view hookSet) xstate+ f <- (MaybeT . return . lookupPathFromId) hset+ file' <- MaybeT (f (B.unpack lid))+ guard ((B.unpack file) /= file')+ let link = LinkAnchor i lid (B.pack file') aid bstr pos dim+ menuitemcvt <- liftIO $ Gtk.menuItemNewWithLabel + ("Correct Path to " ++ show file' :: String) + liftIO (menuitemcvt `Gtk.on` Gtk.menuItemActivate $ + ( evhandler + . UsrEv + . GotContextMenuSignal + . CMenuLinkConvert) link)+ liftIO $ Gtk.menuAttach menu menuitemcvt 0 1 4 5 + return () - _ -> do- let (links,others) = partition ((||) <$> isLinkInRItem <*> isAnchorInRItem) sitms - case links of - l : [] -> do- menuitemreplace <- menuItemNewWithLabel ("replace link/anchor render")- menuitemreplace `on` menuItemActivate $ do- let cache = xstate ^. renderCache- ulbbox = (unUnion . mconcat . fmap (Union . Middle . getBBox)) others- case ulbbox of - Middle bbox -> do- let BBox (x0,y0) (x1,y1) = bbox- dim = Dim (x1-x0) (y1-y0)- svg <- svg_render <$> makeSVGFromSelection cache others bbox- let mitm = case l of - RItemLink lnkbbx _ -> (Just . ItemLink) ((bbxed_content lnkbbx) { link_render = svg, link_dim = dim })- RItemAnchor ancbbx _ -> (Just . ItemAnchor) ((bbxed_content ancbbx) { anchor_render = svg, anchor_dim = dim })- _ -> Nothing - maybe (return ()) (evhandler . UsrEv . GotContextMenuSignal . CMenuConvertSelection ) mitm- _ -> return ()- menuAttach menu menuitemreplace 0 1 8 9- _ -> return ()+ RItemSVG svgbbx _msfc -> do+ let svg = bbxed_content svgbbx+ BBox (x0,y0) (x1,y1) = getBBox svgbbx+ forM_ ((,) <$> svg_text svg <*> svg_command svg) $ \(btxt,cmd) -> do+ let txt = TE.decodeUtf8 btxt+ case cmd of + "pango" -> do + menuitemedt <- Gtk.menuItemNewWithLabel ("Edit Text" :: String) + menuitemedt `Gtk.on` Gtk.menuItemActivate $ do + evhandler (UsrEv (GotContextMenuSignal (CMenuPangoConvert (x0,y0) txt)))+ Gtk.menuAttach menu menuitemedt 0 1 4 5+ return ()+ "latex" -> do + menuitemedt <- Gtk.menuItemNewWithLabel ("Edit LaTeX" :: String)+ menuitemedt `Gtk.on` Gtk.menuItemActivate $ do+ evhandler (UsrEv (GotContextMenuSignal (CMenuLaTeXConvert (x0,y0) txt)))+ Gtk.menuAttach menu menuitemedt 0 1 4 5 + --+#ifdef HUB+ menuitemnet <- Gtk.menuItemNewWithLabel ("Edit LaTeX Network" :: String)+ menuitemnet `Gtk.on` Gtk.menuItemActivate $ do+ evhandler (UsrEv (GotContextMenuSignal (CMenuLaTeXConvertNetwork (x0,y0) txt)))+ Gtk.menuAttach menu menuitemnet 0 1 5 6+ return ()+#endif+ -- + let (txth,txtt) = T.splitAt 19 txt + when ( txth == "embedlatex:keyword:" ) $ do+ menuitemup <- Gtk.menuItemNewWithLabel ("Update LaTeX" :: String)+ menuitemup `Gtk.on` Gtk.menuItemActivate $ do+ evhandler (UsrEv (GotContextMenuSignal (CMenuLaTeXUpdate (x0,y0) (Dim (x1-x0) (y1-y0)) txtt)))+ Gtk.menuAttach menu menuitemup 0 1 6 7+ return () - case (customContextMenuTitle =<< view hookSet xstate) of - Nothing -> return () - Just ttl -> do - custommenu <- menuItemNewWithLabel ttl - custommenu `on` menuItemActivate $ - evhandler (UsrEv (GotContextMenuSignal (CMenuCustom)))- menuAttach menu custommenu 0 1 0 1 + _ -> return ()+ RItemImage imgbbx _msfc -> do+ menuitemcrop <- Gtk.menuItemNewWithLabel ("Crop Image" :: String) + menuitemcrop `Gtk.on` Gtk.menuItemActivate $ do + (evhandler . UsrEv . GotContextMenuSignal . CMenuCropImage) imgbbx+ menuitemrotcw <- Gtk.menuItemNewWithLabel ("Rotate Image CW" :: String) + menuitemrotcw `Gtk.on` Gtk.menuItemActivate $ do + (evhandler . UsrEv . GotContextMenuSignal) (CMenuRotate CW imgbbx)+ menuitemrotccw <- Gtk.menuItemNewWithLabel ("Rotate Image CCW" :: String) + menuitemrotccw `Gtk.on` Gtk.menuItemActivate $ do + (evhandler . UsrEv . GotContextMenuSignal) (CMenuRotate CCW imgbbx)+ menuitemexport <- Gtk.menuItemNewWithLabel ("Export Image" :: String)+ menuitemexport `Gtk.on` Gtk.menuItemActivate $ do+ (evhandler . UsrEv . GotContextMenuSignal) (CMenuExport imgbbx)+ -- + Gtk.menuAttach menu menuitemcrop 0 1 4 5+ Gtk.menuAttach menu menuitemrotcw 0 1 5 6+ Gtk.menuAttach menu menuitemrotccw 0 1 6 7+ Gtk.menuAttach menu menuitemexport 0 1 7 8+ -- + return ()+ RItemAnchor ancbbx _ -> do+ menuitemmklnk <- Gtk.menuItemNewWithLabel ("Link to this anchor" :: String)+ menuitemmklnk `Gtk.on` Gtk.menuItemActivate $+ ( evhandler + . UsrEv + . GotContextMenuSignal + . CMenuMakeLinkToAnchor + . bbxed_content) ancbbx+ Gtk.menuAttach menu menuitemmklnk 0 1 4 5 + _ -> return () - menuitem8 <- menuItemNewWithLabel "Autosave This Page Image"- menuitem8 `on` menuItemActivate $ - evhandler (UsrEv (GotContextMenuSignal (CMenuAutosavePage)))- menuAttach menu menuitem8 1 2 4 5 + _ -> do+ let (links,others) = partition ((||) <$> isLinkInRItem <*> isAnchorInRItem) sitms + case links of + l : [] -> do+ menuitemreplace <- Gtk.menuItemNewWithLabel ("replace link/anchor render" :: String)+ menuitemreplace `Gtk.on` Gtk.menuItemActivate $ do+ cache <- readTVarIO (xstate ^. renderCacheVar)+ let ulbbox = (unUnion . mconcat . fmap (Union . Middle . getBBox)) others+ case ulbbox of + Middle bbox -> do+ let BBox (x0,y0) (x1,y1) = bbox+ dim = Dim (x1-x0) (y1-y0)+ svg <- svg_render <$> makeSVGFromSelection cache cid others bbox+ let mitm = case l of + RItemLink lnkbbx _ -> (Just . ItemLink) ((bbxed_content lnkbbx) { link_render = svg, link_dim = dim })+ RItemAnchor ancbbx _ -> (Just . ItemAnchor) ((bbxed_content ancbbx) { anchor_render = svg, anchor_dim = dim })+ _ -> Nothing + maybe (return ()) (evhandler . UsrEv . GotContextMenuSignal . CMenuConvertSelection ) mitm+ _ -> return ()+ Gtk.menuAttach menu menuitemreplace 0 1 8 9+ _ -> return () - runStateT (mapM_ (makeMenu evhandler menu cid) cids) 0 - widgetShowAll menu - menuPopup menu Nothing - return (UsrEv ContextMenuCreated)+ case (customContextMenuTitle =<< view hookSet xstate) of + Nothing -> return () + Just ttl -> do + custommenu <- Gtk.menuItemNewWithLabel ttl + custommenu `Gtk.on` Gtk.menuItemActivate $ + evhandler (UsrEv (GotContextMenuSignal (CMenuCustom)))+ Gtk.menuAttach menu custommenu 0 1 0 1 + menuitem8 <- Gtk.menuItemNewWithLabel ("Autosave This Page Image" :: String)+ menuitem8 `Gtk.on` Gtk.menuItemActivate $ + evhandler (UsrEv (GotContextMenuSignal (CMenuAutosavePage)))+ Gtk.menuAttach menu menuitem8 1 2 4 5 ++ runStateT (mapM_ (makeMenu evhandler menu cid) cids) 0 + Gtk.widgetShowAll menu + Gtk.menuPopup menu Nothing + return (UsrEv ContextMenuCreated)+ makeMenu evhdlr mn currcid cid = when (currcid /= cid) $ do n <- get- mi <- liftIO $ menuItemNewWithLabel ("Show here in cvs" ++ show cid)- liftIO $ mi `on` menuItemActivate $ + mi <- liftIO $ Gtk.menuItemNewWithLabel ("Show here in cvs" ++ show cid)+ liftIO $ mi `Gtk.on` Gtk.menuItemActivate $ evhdlr (UsrEv (GotContextMenuSignal (CMenuCanvasView cid pnum x y)))- liftIO $ menuAttach mn mi 2 3 n (n+1) + liftIO $ Gtk.menuAttach mn mi 2 3 n (n+1) put (n+1)
src/Hoodle/Coroutine/Default.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiWayIf #-}@@ -7,9 +8,9 @@ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Coroutine.Default --- Copyright : (c) 2011-2014 Ian-Woo Kim+-- Copyright : (c) 2011-2015 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -20,67 +21,53 @@ import Control.Applicative hiding (empty) import Control.Concurrent -import Control.Concurrent.STM-import Control.Lens (_1,over,view,set,at,(.~),(%~),(^.))--- import Control.Monad.Reader hiding (mapM_)+import qualified Control.Exception as E+import Control.Lens (over,view,set,at,(.~),(^.),_2) import Control.Monad.State hiding (mapM_) import Control.Monad.Trans.Reader (ReaderT(..)) import qualified Data.ByteString.Char8 as B import Data.Foldable (mapM_) import qualified Data.IntMap as M import Data.IORef +import qualified Data.List as L import Data.Maybe-import Data.Monoid ((<>))-import Data.Sequence (Seq, (<|),(|>), empty, singleton, viewl, ViewL(..))-import qualified Data.Sequence as Seq (null)-import qualified Data.Text as T (unpack)-import Data.Time.Clock-import Data.UUID-import qualified Graphics.Rendering.Cairo as Cairo import qualified Graphics.UI.Gtk as Gtk hiding (get,set)-import qualified Graphics.UI.Gtk.Poppler.Document as Poppler-import qualified Graphics.UI.Gtk.Poppler.Page as Poppler import System.Process +#ifdef HUB+import Data.Time.Clock+import System.Directory+#endif -- from hoodle-platform import Control.Monad.Trans.Crtn.Driver import Control.Monad.Trans.Crtn.Object import Control.Monad.Trans.Crtn.Logger.Simple-import Control.Monad.Trans.Crtn.Queue -import Data.Hoodle.Select-import Data.Hoodle.Simple (Dimension(..), Background(..), defaultHoodle)+import Data.Hoodle.Simple (Dimension(..), Background(..)) import Data.Hoodle.Generic import Graphics.Hoodle.Render-import Graphics.Hoodle.Render.Background+import Graphics.Hoodle.Render.Engine import Graphics.Hoodle.Render.Type -- from this package import Hoodle.Accessor import Hoodle.Coroutine.Callback-import Hoodle.Coroutine.Commit import Hoodle.Coroutine.ContextMenu+import Hoodle.Coroutine.Default.Menu import Hoodle.Coroutine.Draw import Hoodle.Coroutine.Eraser import Hoodle.Coroutine.File-import Hoodle.Coroutine.HandwritingRecognition import Hoodle.Coroutine.Highlighter-import Hoodle.Coroutine.Layer import Hoodle.Coroutine.Link+import Hoodle.Coroutine.Mode import Hoodle.Coroutine.Page import Hoodle.Coroutine.Pen import Hoodle.Coroutine.Scroll import Hoodle.Coroutine.Select-import Hoodle.Coroutine.Select.Clipboard-import Hoodle.Coroutine.TextInput -import Hoodle.Coroutine.Mode import Hoodle.Coroutine.VerticalSpace import Hoodle.Coroutine.Window import Hoodle.Device import Hoodle.GUI.Menu import Hoodle.GUI.Reflect-import Hoodle.ModelAction.File- import Hoodle.ModelAction.Page import Hoodle.ModelAction.Window -import Hoodle.Script import Hoodle.Script.Hook import Hoodle.Type.Canvas import Hoodle.Type.Coroutine@@ -88,14 +75,19 @@ import Hoodle.Type.Event import Hoodle.Type.HoodleState import Hoodle.Type.PageArrangement-import Hoodle.Type.Predefined import Hoodle.Type.Undo import Hoodle.Type.Window import Hoodle.Type.Widget-import Hoodle.Widget.Clock+import Hoodle.Util import Hoodle.Widget.Dispatch -import Hoodle.Widget.Layer import Hoodle.Widget.PanZoom+#ifdef HUB+import Hoodle.Coroutine.Dialog+import Hoodle.Coroutine.HubInternal+import Hoodle.Coroutine.Socket+import Hoodle.Coroutine.TextInput +import Hoodle.Type.Predefined+#endif -- import Prelude hiding (mapM_) @@ -104,143 +96,169 @@ -> Gtk.Window -> Maybe Hook -> Int -- ^ maxundo - -> (Bool,Bool,Bool) -- ^ (xinputbool,usepz,uselyr)- -> Gtk.Statusbar -- ^ status bar + -> (Bool,Bool,Bool,Bool) -- ^ (xinputbool,usepz,uselyr,varcsr) -> IO (EventVar,HoodleState,Gtk.UIManager,Gtk.VBox)-initCoroutine devlst window mhook maxundo (xinputbool,usepz,uselyr) stbar = do +initCoroutine devlst window mhook maxundo (xinputbool,usepz,uselyr,varcsr) = do evar <- newEmptyMVar putMVar evar Nothing + let callback = eventHandler evar st0new <- set deviceList devlst . set rootOfRootWindow window - . set callBack (eventHandler evar) + . set callBack callback <$> emptyHoodleState - -- pdf rendering testing code- let tvar = st0new ^. pdfRenderQueue- -- (ui,uicompsighdlr) <- getMenuUI evar let st1 = set gtkUIManager ui st0new initcvs = set (canvasWidgets.widgetConfig.doesUsePanZoomWidget) usepz . set (canvasWidgets.widgetConfig.doesUseLayerWidget) uselyr $ defaultCvsInfoSinglePage { _canvasId = 1 } initcvsbox = CanvasSinglePage initcvs- st2 = set frameState (Node 1) - . updateFromCanvasInfoAsCurrentCanvas initcvsbox - $ st1 { _cvsInfoMap = M.empty } - (st3,cvs,_wconf) <- constructFrame st2 (view frameState st2)- (st4,wconf') <- eventConnect st3 (view frameState st3)- -- testing- -- let handler = const (putStrLn "In getFileContent, got call back")- -- newhdl <- flip runReaderT (undefined,undefined) . cnstrctRHoodle =<< defaultHoodle- -- let nhmodstate = ViewAppendState newhdl + st2 = st1 # over (unitHoodles.currentUnit) ( set frameState (Node 1) + . updateFromCanvasInfoAsCurrentCanvas initcvsbox + . set cvsInfoMap M.empty )+ uhdl2 = view (unitHoodles.currentUnit) st2+ (uhdl3,cvs,_wconf) <- constructFrame st2 uhdl2 (view frameState uhdl2)+ (uhdl4,wconf') <- eventConnect st2 uhdl3 (view frameState uhdl3)+ notebook <- Gtk.notebookNew+ statusbar <- Gtk.statusbarNew+#ifdef HUB+ let sqlinfo = (join . fmap sqliteInfo) mhook +#endif+ let st4 = (unitHoodles.currentUnit .~ uhdl4) st2+ st5 = st4 # over (unitHoodles.currentUnit) + ( set undoTable (emptyUndo maxundo) + . set frameState wconf' + . set rootWindow cvs + . set (hoodleFileControl.hoodleFileName) (LocalDir Nothing))+ . set (settings.doesUseXInput) xinputbool + . set (settings.doesUseVariableCursor) varcsr+#ifdef HUB+ . set (settings.sqliteFileName) sqlinfo+#endif+ . set hookSet mhook + . set rootNotebook notebook+ . set uiComponentSignalHandler uicompsighdlr + . set statusBar (Just statusbar) - let st5 = set (settings.doesUseXInput) xinputbool - . set hookSet mhook - . set undoTable (emptyUndo maxundo) - . set frameState wconf' - . set rootWindow cvs - . set uiComponentSignalHandler uicompsighdlr - . set statusBar (Just stbar)- . set (hoodleFileControl.hoodleFileName) Nothing - -- . set hoodleModeState nhmodstate- $ st4 vbox <- Gtk.vBoxNew False 0 - -- - let startingXstate = set rootContainer (Gtk.castToBox vbox) st5- let startworld = world startingXstate . ReaderT $ - (\(Arg DoEvent ev) -> guiProcess ev) + Gtk.containerAdd window vbox+ vboxcvs <- Gtk.vBoxNew False 0 + -- Gtk.notebookAppendPage notebook vboxcvs ("untitled" :: T.Text)+ (_,uuid,btn) <- createTab callback notebook vboxcvs+ Gtk.containerAdd vboxcvs (view (unitHoodles.currentUnit.rootWindow) st5)++ sigid <- notebook `Gtk.on` Gtk.switchPage $ \i -> callback (UsrEv (SwitchTab i)) + let st6 = ( (unitHoodles.currentUnit.unitUUID .~ uuid) + . (unitHoodles.currentUnit.unitButton .~ btn)+ . (uiComponentSignalHandler.switchTabSignal .~ Just sigid)) st5+ -- st6 = st5+ startingXstate = (unitHoodles.currentUnit.rootContainer .~ Gtk.castToBox vboxcvs) st6+ startworld = world startingXstate . ReaderT $ (\(Arg DoEvent ev) -> guiProcess ev) putMVar evar . Just $ (driver simplelogger startworld) return (evar,startingXstate,ui,vbox) - -- | initialization according to the setting -initialize :: AllEvent -> MainCoroutine ()-initialize ev = do +initialize :: Maybe (CanvasId,CanvasDimension) -> Bool -> AllEvent -> MainCoroutine (CanvasId, CanvasDimension)+initialize cvs isInitialized ev = do case ev of - UsrEv (Initialized mfname) -> do -- additional initialization goes here- xst1 <- get- let tvar = xst1 ^. pdfRenderQueue- doIOaction $ \evhandler -> do - let handler = Gtk.postGUIAsync . evhandler . SysEv . RenderCacheUpdate- forkOn 2 $ pdfRendererMain handler tvar- return (UsrEv ActionOrdered)- waitSomeEvent (\case ActionOrdered -> True ; _ -> False ) - - getFileContent mfname-- xst2 <- get- let hdlst = xst2 ^. hoodleModeState - cache = xst2 ^. renderCache- hdlst' <- liftIO $ resetHoodleModeStateBuffers cache hdlst- put (set hoodleModeState hdlst' xst2)--- xst <- get - let Just sbar = view statusBar xst - cxtid <- liftIO $ Gtk.statusbarGetContextId sbar "test"- liftIO $ Gtk.statusbarPush sbar cxtid "Hello there" - let ui = view gtkUIManager xst- liftIO $ toggleSave ui False- put (set isSaved True xst) - - _ -> do ev' <- nextevent- initialize (UsrEv ev')-+ UsrEv (Initialized mfname) -> do + if isInitialized + then case cvs of+ Nothing -> nextevent >>= initialize Nothing True . UsrEv+ Just cvsi -> return cvsi+ else do+ -- additional initialization goes here+ xst1 <- get+ let ui = xst1 ^. gtkUIManager+ cachevar = xst1 ^. renderCacheVar+ tvarpdf = xst1 ^. pdfRenderQueue+ tvargen = xst1 ^. genRenderQueue+ doIOaction $ \evhandler -> do + -- let handler = Gtk.postGUIAsync . evhandler . SysEv . RenderCacheUpdate+ forkOn 2 $ pdfRendererMain (defaultHandler evhandler) tvarpdf+ forkIO $ E.catch (genRendererMain cachevar (defaultHandler evhandler) tvargen) (\e -> print (e :: E.SomeException)) + return (UsrEv ActionOrdered)+ waitSomeEvent (\case ActionOrdered -> True ; _ -> False ) + getFileContent (LocalDir mfname)+ -- + xst2 <- get+ let uhdl = view (unitHoodles.currentUnit) xst2+ hdlst = uhdl ^. hoodleModeState + cid = getCurrentCanvasId uhdl+ callRenderer_ $ resetHoodleModeStateBuffers cid hdlst+ pureUpdateUhdl (hoodleModeState .~ hdlst)+ -- liftIO $ toggleSave ui False+ liftIO $ reflectUIToggle ui "SAVEA" False+ pureUpdateUhdl (isSaved .~ True)+ case cvs of+ Just cvsi -> return cvsi+ Nothing -> nextevent >>= initialize Nothing True . UsrEv+ UsrEv (CanvasConfigure cid w h) -> do+ nextevent >>= initialize (Just (cid,CanvasDimension (Dim w h))) isInitialized . UsrEv + _ -> case (cvs,isInitialized) of+ (Just cvsi,True) -> return cvsi+ _ -> nextevent >>= initialize cvs isInitialized . UsrEv -- | guiProcess :: AllEvent -> MainCoroutine () guiProcess ev = do - initialize ev- changePage (const 0)- xstate <- get - reflectViewModeUI- reflectPenModeUI- reflectPenColorUI - reflectPenWidthUI- let cinfoMap = getCanvasInfoMap xstate-- assocs = M.toList cinfoMap - f (cid,cinfobox) = do let canvas = getDrawAreaFromBox cinfobox- (w',h') <- liftIO $ Gtk.widgetGetSize canvas- liftIO $ print (w',h')--- defaultEventProcess (CanvasConfigure cid--- (fromIntegral w') --- (fromIntegral h')) - - mapM_ f assocs- - viewModeChange ToContSinglePage- pageZoomChange FitWidth-- -- waitSomeEvent (\x -> case x of CanvasConfigure cid w h -> True ; _ -> False)- -- startLinkReceiver- -- main loop - sequence_ (repeat dispatchMode)+ (cid,cdim) <- initialize Nothing False ev+ liftIO $ print (cid,cdim)+ changePage (const 0)+ reflectViewModeUI+ reflectPenModeUI+ reflectPenColorUI + reflectPenWidthUI+ reflectNewPageModeUI+ viewModeChange ToContSinglePage+ pageZoomChange FitWidth+#ifdef HUB+ initSqliteDB+ startLinkReceiver+ socketConnect+ syncFile+#endif+ doCanvasConfigure cid cdim+ -- main loop + sequence_ (repeat dispatchMode) -- | dispatchMode :: MainCoroutine () -dispatchMode = get >>= return . hoodleModeStateEither . view hoodleModeState- >>= either (const viewAppendMode) (const selectMode)+dispatchMode = (view (unitHoodles.currentUnit) <$> get) + >>= return . hoodleModeStateEither . view hoodleModeState+ >>= either (const viewAppendMode) (const selectMode) -- | viewAppendMode :: MainCoroutine () viewAppendMode = do r1 <- nextevent case r1 of - PenDown cid pbtn pcoord -> do + PenDown cid pbtn pcoord -> widgetCheckPen cid pcoord $ do ptype <- getPenType case (ptype,pbtn) of - (PenWork,PenButton1) -> penStart cid pcoord+ (PenWork,PenButton1) -> do+ r <- penStart cid pcoord+ case r of + Just (Just Nothing) -> do + pureUpdateUhdl (isOneTimeSelectMode .~ YesBeforeSelect)+ modeChange ToSelectMode+ selectLassoStart PenButton3 cid pcoord+ _ -> return () (PenWork,PenButton2) -> eraserStart cid pcoord (PenWork,PenButton3) -> do - updateXState (return . set isOneTimeSelectMode YesBeforeSelect)+ pureUpdateUhdl (isOneTimeSelectMode .~ YesBeforeSelect) modeChange ToSelectMode selectLassoStart PenButton3 cid pcoord (PenWork,EraserButton) -> eraserStart cid pcoord (PenWork,_) -> return () (EraserWork,_) -> eraserStart cid pcoord - (HighlighterWork,_) -> highlighterStart cid pcoord+ (HighlighterWork,_) -> do + r <- highlighterStart cid pcoord + case r of + Just (Just Nothing) -> do + pureUpdateUhdl (isOneTimeSelectMode .~ YesBeforeSelect)+ modeChange ToSelectMode+ selectLassoStart PenButton3 cid pcoord+ _ -> return () (VerticalSpaceWork,PenButton1) -> verticalSpaceStart cid pcoord (VerticalSpaceWork,_) -> return () TouchDown cid pcoord -> touchStart cid pcoord @@ -252,19 +270,15 @@ disableTouch = do xst <- get let devlst = view deviceList xst - let b = view (settings.doesUseTouch) xst - when b $ do + when (view (settings.doesUseTouch) xst) $ do let nxst = set (settings.doesUseTouch) False xst - doIOaction $ \_ -> do- setToggleUIForFlag "HANDA" (settings.doesUseTouch) nxst+ doIOaction_ $ do+ lensSetToggleUIForFlag "HANDA" (settings.doesUseTouch) nxst let touchstr = dev_touch_str devlst -- ad hoc when (touchstr /= "touch") $ do readProcess "xinput" [ "disable", touchstr ] "" return ()- -- - return (UsrEv ActionOrdered)- waitSomeEvent (\x -> case x of ActionOrdered -> True ; _ -> False) put nxst -- |@@ -298,7 +312,8 @@ defaultEventProcess (VScrollBarMoved cid v) = vscrollBarMoved cid v defaultEventProcess (VScrollBarStart cid v) = vscrollStart cid v defaultEventProcess PaneMoveStart = paneMoveStart -defaultEventProcess (CanvasConfigure cid w' h') = doCanvasConfigure cid (CanvasDimension (Dim w' h'))+defaultEventProcess (CanvasConfigure cid w' h') = + doCanvasConfigure cid (CanvasDimension (Dim w' h')) defaultEventProcess ToViewAppendMode = modeChange ToViewAppendMode defaultEventProcess ToSelectMode = modeChange ToSelectMode defaultEventProcess ToSinglePage = viewModeChange ToSinglePage@@ -323,9 +338,9 @@ reflectPenWidthUI defaultEventProcess (BackgroundStyleChanged bsty) = do modify (backgroundStyle .~ bsty)- xstate <- get - let pgnum = view (currentCanvasInfo . unboxLens currentPageNum) xstate- hdl = getHoodle xstate + uhdl <- view (unitHoodles.currentUnit) <$> get + let pgnum = view (currentCanvasInfo . unboxLens currentPageNum) uhdl+ hdl = getHoodle uhdl pgs = view gpages hdl cpage = getPageFromGHoodleMap pgnum hdl cbkg = view gbackground cpage@@ -347,41 +362,36 @@ npgs = set (at pgnum) (Just npage) pgs nhdl = set gpages npgs hdl modeChange ToViewAppendMode - modify (set hoodleModeState (ViewAppendState nhdl))+ pureUpdateUhdl (hoodleModeState .~ ViewAppendState nhdl) invalidateAll +defaultEventProcess (AssignNewPageMode nmod) = modify (settings.newPageMode .~ nmod) defaultEventProcess (GotContextMenuSignal ctxtmenu) = processContextMenu ctxtmenu defaultEventProcess (GetHoodleFileInfo ref) = do - xst <- get- let hdl = getHoodle xst + uhdl <- view (unitHoodles.currentUnit) <$> get+ let hdl = getHoodle uhdl uuid = B.unpack (view ghoodleID hdl)- case view (hoodleFileControl.hoodleFileName) xst of + case getHoodleFilePath uhdl of Nothing -> liftIO $ writeIORef ref Nothing Just fp -> liftIO $ writeIORef ref (Just (uuid ++ "," ++ fp))+defaultEventProcess (GetHoodleFileInfoFromTab uuidtab ref) = do + uhdlmap <- view (unitHoodles._2) <$> get+ let muhdl = (L.lookup uuidtab . map (\x -> (view unitUUID x,x)) . M.elems) uhdlmap+ case muhdl of + Nothing -> liftIO $ writeIORef ref Nothing+ Just uhdl -> do + let hdl = getHoodle uhdl+ uuid = B.unpack (view ghoodleID hdl)+ case getHoodleFilePath uhdl of + Nothing -> liftIO $ writeIORef ref Nothing+ Just fp -> liftIO $ writeIORef ref (Just (uuid ++ "," ++ fp)) defaultEventProcess (GotLink mstr (x,y)) = gotLink mstr (x,y) -defaultEventProcess (Sync ctime) = do - xst <- get- case view (hoodleFileControl.lastSavedTime) xst of - Nothing -> return ()- Just otime -> do - let dtime = diffUTCTime ctime otime- if dtime < dtime_bound * 10 - then return () - else do - let ioact = mkIOaction $ \evhandler -> do - Gtk.postGUISync (evhandler (UsrEv FileReloadOrdered))- return (UsrEv ActionOrdered)- modify (tempQueue %~ enqueue ioact)+ defaultEventProcess FileReloadOrdered = fileReload defaultEventProcess (CustomKeyEvent str) = do- liftIO $ print str if | str == "[]:\"Super_L\"" -> do xst <- liftM (over (settings.doesUseTouch) not) get put xst - let action = mkIOaction $ \_evhandler -> do - setToggleUIForFlag "HANDA" (settings.doesUseTouch) xst- return (UsrEv ActionOrdered)- modify (tempQueue %~ enqueue action)- waitSomeEvent (\x -> case x of ActionOrdered -> True ; _ -> False) + doIOaction_ $ lensSetToggleUIForFlag "HANDA" (settings.doesUseTouch) xst toggleTouch | str == "[]:\"1\"" -> colorfunc ColorBlack | str == "[]:\"2\"" -> colorfunc ColorBlue @@ -402,210 +412,45 @@ where colorfunc c = doIOaction $ \_evhandler -> return (UsrEv (PenColorChanged c)) toolfunc t = doIOaction $ \_evhandler -> return (UsrEv (AssignPenMode (Left t)))+defaultEventProcess (SwitchTab i) = switchTab i+defaultEventProcess (CloseTab uuid) = findTab uuid >>= mapM_ (\x-> switchTab x >> askIfSave closeTab)+defaultEventProcess (OpenLink urlpath mid) = openLinkAction urlpath mid+#ifdef HUB+defaultEventProcess (OpenShared uuid) = openShared uuid+defaultEventProcess (OpenTemp _uuid tmpfile) = getFileContent (TempDir tmpfile)+ >> canvasZoomUpdateAll + >> invalidateAll+defaultEventProcess (NetworkProcess (NetworkReceived txt)) = networkReceived txt defaultEventProcess (DBusEv (ImageFileDropped fname)) = embedImage fname defaultEventProcess (DBusEv (DBusNetworkInput txt)) = dbusNetworkInput txt defaultEventProcess (DBusEv (GoToLink (docid,anchorid))) = goToAnchorPos docid anchorid-defaultEventProcess ev = -- for debugging- do liftIO $ putStrLn "--- no default ---"- liftIO $ print ev - liftIO $ putStrLn "------------------"- return () ---- |-menuEventProcess :: MenuEvent -> MainCoroutine () -menuEventProcess MenuQuit = do - xstate <- get- liftIO $ putStrLn "MenuQuit called"- if view isSaved xstate - then liftIO $ Gtk.mainQuit- else askQuitProgram-menuEventProcess MenuPreviousPage = changePage (\x->x-1)-menuEventProcess MenuNextPage = changePage (+1)-menuEventProcess MenuFirstPage = changePage (const 0)-menuEventProcess MenuLastPage = do - totalnumofpages <- (either (M.size. view gpages) (M.size . view gselAll) - . hoodleModeStateEither . view hoodleModeState) <$> get - changePage (const (totalnumofpages-1))-menuEventProcess MenuNewPageBefore = newPage PageBefore -menuEventProcess MenuNewPageAfter = newPage PageAfter-menuEventProcess MenuDeletePage = deleteCurrentPage-menuEventProcess MenuExportPageSVG = exportCurrentPageAsSVG -menuEventProcess MenuNew = askIfSave fileNew -menuEventProcess MenuAnnotatePDF = askIfSave fileAnnotatePDF-menuEventProcess MenuLoadPNGorJPG = fileLoadPNGorJPG-menuEventProcess MenuLoadSVG = fileLoadSVG-menuEventProcess MenuText = textInput (Just (100,100)) "" -menuEventProcess MenuEmbedTextSource = embedTextSource-menuEventProcess MenuEditEmbedTextSource = editEmbeddedTextSource-menuEventProcess MenuEditNetEmbedTextSource = editNetEmbeddedTextSource-menuEventProcess MenuTextFromSource = textInputFromSource (100,100)-menuEventProcess MenuLaTeX = - laTeXInput Nothing (laTeXHeader <> "\n\n" <> laTeXFooter)-menuEventProcess MenuLaTeXNetwork = - laTeXInputNetwork Nothing (laTeXHeader <> "\n\n" <> laTeXFooter) -menuEventProcess MenuCombineLaTeX = combineLaTeXText -menuEventProcess MenuLaTeXFromSource = laTeXInputFromSource (100,100)-menuEventProcess MenuUndo = undo -menuEventProcess MenuRedo = redo-menuEventProcess MenuOpen = askIfSave fileOpen-menuEventProcess MenuSave = fileSave -menuEventProcess MenuSaveAs = fileSaveAs-menuEventProcess MenuReload = fileReload -menuEventProcess MenuExport = fileExport -menuEventProcess MenuStartSync = fileStartSync-menuEventProcess MenuVersionSave = fileVersionSave -menuEventProcess MenuShowRevisions = fileShowRevisions-menuEventProcess MenuShowUUID = fileShowUUID--- -menuEventProcess MenuCut = cutSelection-menuEventProcess MenuCopy = copySelection-menuEventProcess MenuPaste = pasteToSelection-menuEventProcess MenuDelete = deleteSelection-menuEventProcess MenuZoomIn = pageZoomChangeRel ZoomIn -menuEventProcess MenuZoomOut = pageZoomChangeRel ZoomOut-menuEventProcess MenuNormalSize = pageZoomChange Original -menuEventProcess MenuPageWidth = pageZoomChange FitWidth -menuEventProcess MenuPageHeight = pageZoomChange FitHeight-menuEventProcess MenuHSplit = eitherSplit SplitHorizontal-menuEventProcess MenuVSplit = eitherSplit SplitVertical-menuEventProcess MenuDelCanvas = deleteCanvas-menuEventProcess MenuNewLayer = makeNewLayer -menuEventProcess MenuNextLayer = gotoNextLayer -menuEventProcess MenuPrevLayer = gotoPrevLayer-menuEventProcess MenuGotoLayer = startGotoLayerAt -menuEventProcess MenuDeleteLayer = deleteCurrentLayer-menuEventProcess MenuUseXInput = do - xstate <- get - b <- updateFlagFromToggleUI "UXINPUTA" (settings.doesUseXInput)- let cmap = getCanvasInfoMap xstate- canvases = map (getDrawAreaFromBox) . M.elems $ cmap - if b- then mapM_ (\x->liftIO $ Gtk.widgetSetExtensionEvents x [Gtk.ExtensionEventsAll]) canvases- else mapM_ (\x->liftIO $ Gtk.widgetSetExtensionEvents x [Gtk.ExtensionEventsNone] ) canvases-menuEventProcess MenuUseTouch = toggleTouch-menuEventProcess MenuSmoothScroll = updateFlagFromToggleUI "SMTHSCRA" (settings.doesSmoothScroll) >> return ()-menuEventProcess MenuUsePopUpMenu = updateFlagFromToggleUI "POPMENUA" (settings.doesUsePopUpMenu) >> return ()-menuEventProcess MenuEmbedImage = updateFlagFromToggleUI "EBDIMGA" (settings.doesEmbedImage) >> return ()-menuEventProcess MenuEmbedPDF = updateFlagFromToggleUI "EBDPDFA" (settings.doesEmbedPDF) >> return ()-menuEventProcess MenuFollowLinks = updateFlagFromToggleUI "FLWLNKA" (settings.doesFollowLinks) >> return ()-menuEventProcess MenuKeepAspectRatio = updateFlagFromToggleUI "KEEPRATIOA" (settings.doesKeepAspectRatio) >> return ()-menuEventProcess MenuUseVariableCursor = updateFlagFromToggleUI "VCURSORA" (settings.doesUseVariableCursor) >> reflectCursor >> return ()-menuEventProcess MenuPressureSensitivity = updateFlagFromToggleUI "PRESSRSENSA" (penInfo.variableWidthPen) >> return () -menuEventProcess MenuRelaunch = liftIO $ relaunchApplication-menuEventProcess MenuColorPicker = colorPick -menuEventProcess MenuFullScreen = fullScreen-menuEventProcess MenuAddLink = addLink-menuEventProcess MenuAddAnchor = addAnchor-menuEventProcess MenuListAnchors = listAnchors-menuEventProcess MenuEmbedPredefinedImage = embedPredefinedImage -menuEventProcess MenuEmbedPredefinedImage2 = embedPredefinedImage2 -menuEventProcess MenuEmbedPredefinedImage3 = embedPredefinedImage3 -menuEventProcess MenuApplyToAllPages = do - xstate <- get - let bsty = view backgroundStyle xstate - let hdl = getHoodle xstate - pgs = view gpages hdl - changeBkg cpage = - let cbkg = view gbackground cpage- nbkg - | isRBkgSmpl cbkg = cbkg { rbkg_style = convertBackgroundStyleToByteString bsty }- | otherwise = cbkg - in set gbackground nbkg cpage - npgs = fmap changeBkg pgs - nhdl = set gpages npgs hdl - modeChange ToViewAppendMode - modify (set hoodleModeState (ViewAppendState nhdl))- invalidateAll -menuEventProcess MenuEmbedAllPDFBkg = embedAllPDFBackground-menuEventProcess MenuTogglePanZoomWidget = (togglePanZoom . view (currentCanvas._1)) =<< get -menuEventProcess MenuToggleLayerWidget = (toggleLayer . view (currentCanvas._1)) =<< get -menuEventProcess MenuToggleClockWidget = (toggleClock . view (currentCanvas._1)) =<< get-menuEventProcess MenuHandwritingRecognitionDialog = - handwritingRecognitionDialog >>= mapM_ (\(b,txt) -> when b $ embedHoodlet (T.unpack txt)) -menuEventProcess m = liftIO $ putStrLn $ "not implemented " ++ show m ----- | -colorPick :: MainCoroutine () -colorPick = do mc <- colorPickerBox "Pen Color" - maybe (return ()) - (\c->modify (penInfo.currentTool.penColor .~ c)) - mc ---- | -colorConvert :: Gtk.Color -> PenColor -colorConvert (Gtk.Color r g b) = ColorRGBA (realToFrac r/65536.0) (realToFrac g/65536.0) (realToFrac b/65536.0) 1.0 ---- | -colorPickerBox :: String -> MainCoroutine (Maybe PenColor) -colorPickerBox msg = do - xst <- get - let pcolor = view ( penInfo.currentTool.penColor) xst - modify (tempQueue %~ enqueue (action pcolor)) >> go - where - action pcolor = - mkIOaction $ - \_evhandler -> do - dialog <- Gtk.colorSelectionDialogNew msg- csel <- Gtk.colorSelectionDialogGetColor dialog- let (r,g,b,_a) = convertPenColorToRGBA pcolor - color = Gtk.Color (floor (r*65535.0)) (floor (g*65535.0)) (floor (b*65535.0))- - Gtk.colorSelectionSetCurrentColor csel color- res <- Gtk.dialogRun dialog - mc <- case res of - Gtk.ResponseOk -> do - clrsel <- Gtk.colorSelectionDialogGetColor dialog - clr <- Gtk.colorSelectionGetCurrentColor clrsel - return (Just (colorConvert clr))- _ -> return Nothing - Gtk.widgetDestroy dialog - return (UsrEv (ColorChosen mc))- go = do r <- nextevent - case r of - ColorChosen mc -> return mc - UpdateCanvas cid -> -- this is temporary- invalidateInBBox Nothing Efficient cid >> go- _ -> go ---pdfRendererMain :: ((UUID,(Double,Cairo.Surface))->IO ()) -> TVar (Seq (UUID,PDFCommand)) -> IO () -pdfRendererMain handler tvar = forever $ do - -- putStrLn "pdfRenderMain called"- p <- atomically $ do - lst' <- readTVar tvar- case viewl lst' of- EmptyL -> retry- p :< ps -> do - writeTVar tvar ps - return p - pdfWorker handler p--pdfWorker :: ((UUID,(Double,Cairo.Surface))->IO ()) -> (UUID,PDFCommand) -> IO ()-pdfWorker _handler (_,GetDocFromFile fp tmvar) = do- -- putStrLn "pdfWorker : GetDocFromFile"- mdoc <- popplerGetDocFromFile fp- atomically $ putTMVar tmvar mdoc -pdfWorker _handler (_,GetDocFromDataURI str tmvar) = do- -- putStrLn "pdfWorker : GetDocFromDataURI"- mdoc <- popplerGetDocFromDataURI str- atomically $ putTMVar tmvar mdoc-pdfWorker _handler (_,GetPageFromDoc doc pn tmvar) = do- -- putStrLn "pdfWorker : GetPageFromDoc"- mpg <- popplerGetPageFromDoc doc pn- atomically $ putTMVar tmvar mpg-pdfWorker handler (uuid,RenderPageScaled page (Dim ow oh) (Dim w h)) = do- -- putStrLn "pdfWorker : RenderPageScaled"- let s = w / ow- sfc <- Cairo.createImageSurface Cairo.FormatARGB32 (floor w) (floor h)- Cairo.renderWith sfc $ do - Cairo.setSourceRGBA 1 1 1 1- Cairo.rectangle 0 0 w h - Cairo.fill- Cairo.scale s s- Poppler.pageRender page - handler (uuid,(s,sfc))--+defaultEventProcess (DisconnectedHub tokfile (ofile,file) hinfo) = do+ b <- okCancelMessageBox "authentication failure! do you want to start from the beginning?"+ when b $ do+ r' :: Either E.SomeException () <- liftIO (E.try (removeFile tokfile))+ case r' of + Left _ -> msgShout "DisconnectedHub" >> return ()+ Right _ -> uploadWork (ofile,file) hinfo+defaultEventProcess (Sync ctime) = do + xst <- get+ case view (unitHoodles.currentUnit.hoodleFileControl.lastSavedTime) xst of + Nothing -> return ()+ Just otime -> do + let dtime = diffUTCTime ctime otime+ if dtime < dtime_bound * 10 + then return () + else + doIOaction $ \evhandler -> do + Gtk.postGUISync (evhandler (UsrEv FileReloadOrdered))+ return (UsrEv ActionOrdered)+defaultEventProcess (SyncInfoUpdated uhdluuid fstat) = updateSyncInfo uhdluuid fstat+defaultEventProcess (SyncFileFinished fstat) = updateSyncInfoAll fstat+defaultEventProcess (FileSyncFromHub uhdluuid fstat) = fileSyncFromHub uhdluuid fstat+defaultEventProcess (GotSyncEvent isforced fileuuid uhdluuid) = gotSyncEvent isforced fileuuid uhdluuid+#endif +defaultEventProcess ev = -- for debugging+ do msgShout "--- no default ---"+ msgShout (show ev)+ msgShout "------------------"
+ src/Hoodle/Coroutine/Default/Menu.hs view
@@ -0,0 +1,239 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++-----------------------------------------------------------------------------+-- |+-- Module : Hoodle.Coroutine.Default.Menu+-- Copyright : (c) 2014, 2015 Ian-Woo Kim+--+-- License : BSD3+-- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>+-- Stability : experimental+-- Portability : GHC+--+-----------------------------------------------------------------------------++module Hoodle.Coroutine.Default.Menu where++import Control.Applicative+import Control.Lens (_1,view,set,(.~))+import Control.Monad.IO.Class+import Control.Monad.State hiding (mapM_)+import Data.Foldable (mapM_)+import qualified Data.IntMap as M+import Data.Monoid+import qualified Data.Text as T+import qualified Graphics.UI.Gtk as Gtk+--+import Data.Hoodle.Generic+import Data.Hoodle.Select+import Graphics.Hoodle.Render.Type+--+import Hoodle.Accessor+import Hoodle.Coroutine.Commit+import Hoodle.Coroutine.Draw+import Hoodle.Coroutine.File+import Hoodle.Coroutine.HandwritingRecognition+import Hoodle.Coroutine.LaTeX+import Hoodle.Coroutine.Layer+import Hoodle.Coroutine.Link+import Hoodle.Coroutine.Mode+import Hoodle.Coroutine.Page+import Hoodle.Coroutine.Select.Clipboard+import Hoodle.Coroutine.TextInput+import Hoodle.Coroutine.Window+import Hoodle.GUI.Reflect+import Hoodle.Type.Canvas+import Hoodle.Type.Coroutine+import Hoodle.Type.Enum+import Hoodle.Type.Event+import Hoodle.Type.HoodleState+import Hoodle.Type.PageArrangement+import Hoodle.Type.Window+import Hoodle.Widget.Clock+import Hoodle.Widget.Layer+import Hoodle.Widget.PanZoom+import Hoodle.Widget.Scroll+#ifdef HUB+import Hoodle.Coroutine.Hub+#endif+#ifdef DYRE+import Hoodle.Script+#endif+--+import Prelude hiding (mapM_)++++-- |+menuEventProcess :: MenuEvent -> MainCoroutine () +menuEventProcess MenuQuit = do + xstate <- get+ if view (unitHoodles.currentUnit.isSaved) xstate + then liftIO $ Gtk.mainQuit+ else askQuitProgram+menuEventProcess MenuPreviousPage = changePage (\x->x-1)+menuEventProcess MenuNextPage = changePage (+1)+menuEventProcess MenuFirstPage = changePage (const 0)+menuEventProcess MenuLastPage = do + totalnumofpages <- (either (M.size. view gpages) (M.size . view gselAll) + . hoodleModeStateEither . view (unitHoodles.currentUnit.hoodleModeState)) <$> get + changePage (const (totalnumofpages-1))+menuEventProcess MenuNewPageBefore = newPage Nothing PageBefore +menuEventProcess MenuNewPageAfter = newPage Nothing PageAfter+menuEventProcess MenuDeletePage = deleteCurrentPage+menuEventProcess MenuExportPageSVG = exportCurrentPageAsSVG +menuEventProcess MenuNew = addTab (LocalDir Nothing) -- askIfSave fileNew +menuEventProcess MenuAnnotatePDF = askIfSave fileAnnotatePDF+menuEventProcess MenuLoadPNGorJPG = fileLoadPNGorJPG+menuEventProcess MenuLoadSVG = fileLoadSVG+menuEventProcess MenuLoadImageBackground = fileLoadImageBackground+menuEventProcess MenuText = textInput (Just (100,100)) "" +menuEventProcess MenuEmbedTextSource = embedTextSource+menuEventProcess MenuEditEmbedTextSource = editEmbeddedTextSource+menuEventProcess MenuTextFromSource = textInputFromSource (100,100)+menuEventProcess MenuLaTeX = + laTeXInput Nothing (laTeXHeader <> "\n\n" <> laTeXFooter)+menuEventProcess MenuCombineLaTeX = combineLaTeXText +menuEventProcess MenuLaTeXFromSource = laTeXInputFromSource (100,100)+-- menuEventProcess MenuUpdateLaTeX = updateLaTeX+menuEventProcess MenuUndo = undo +menuEventProcess MenuRedo = redo+menuEventProcess MenuOpen = askIfSave fileOpen+menuEventProcess MenuSave = fileSave +menuEventProcess MenuSaveAs = fileSaveAs+menuEventProcess MenuReload = fileReload +menuEventProcess MenuExport = fileExport +-- menuEventProcess MenuStartSync = fileStartSync+menuEventProcess MenuVersionSave = fileVersionSave +menuEventProcess MenuShowRevisions = fileShowRevisions+menuEventProcess MenuShowUUID = fileShowUUID+-- +menuEventProcess MenuCut = cutSelection+menuEventProcess MenuCopy = copySelection+menuEventProcess MenuPaste = pasteToSelection+menuEventProcess MenuDelete = deleteSelection+menuEventProcess MenuZoomIn = pageZoomChangeRel ZoomIn +menuEventProcess MenuZoomOut = pageZoomChangeRel ZoomOut+menuEventProcess MenuNormalSize = pageZoomChange Original +menuEventProcess MenuPageWidth = pageZoomChange FitWidth +menuEventProcess MenuPageHeight = pageZoomChange FitHeight+menuEventProcess MenuHSplit = eitherSplit SplitHorizontal+menuEventProcess MenuVSplit = eitherSplit SplitVertical+menuEventProcess MenuDelCanvas = deleteCanvas+menuEventProcess MenuNewLayer = makeNewLayer +menuEventProcess MenuNextLayer = gotoNextLayer +menuEventProcess MenuPrevLayer = gotoPrevLayer+menuEventProcess MenuGotoLayer = startGotoLayerAt +menuEventProcess MenuDeleteLayer = deleteCurrentLayer+menuEventProcess MenuUseXInput = do + uhdl <- view (unitHoodles.currentUnit) <$> get + let cmap = view cvsInfoMap uhdl+ canvases = map (getDrawAreaFromBox) . M.elems $ cmap + updateFlagFromToggleUI "UXINPUTA" (settings.doesUseXInput) >>= \b -> +#ifdef GTK3 + return ()+#else+ if b+ then mapM_ (\x->liftIO $ Gtk.widgetSetExtensionEvents x [Gtk.ExtensionEventsAll]) canvases+ else mapM_ (\x->liftIO $ Gtk.widgetSetExtensionEvents x [Gtk.ExtensionEventsNone] ) canvases+#endif+menuEventProcess MenuUseTouch = toggleTouch+menuEventProcess MenuUsePopUpMenu = updateFlagFromToggleUI "POPMENUA" (settings.doesUsePopUpMenu) >> return ()+menuEventProcess MenuEmbedImage = updateFlagFromToggleUI "EBDIMGA" (settings.doesEmbedImage) >> return ()+menuEventProcess MenuEmbedPDF = updateFlagFromToggleUI "EBDPDFA" (settings.doesEmbedPDF) >> return ()+menuEventProcess MenuFollowLinks = updateFlagFromToggleUI "FLWLNKA" (settings.doesFollowLinks) >> return ()+menuEventProcess MenuKeepAspectRatio = updateFlagFromToggleUI "KEEPRATIOA" (settings.doesKeepAspectRatio) >> return ()+menuEventProcess MenuUseVariableCursor = updateFlagFromToggleUI "VCURSORA" (settings.doesUseVariableCursor) >> reflectCursor True >> return ()+menuEventProcess MenuPressureSensitivity = updateFlagFromToggleUI "PRESSRSENSA" (penInfo.variableWidthPen) >> return () +#ifdef DYRE+menuEventProcess MenuRelaunch = liftIO $ relaunchApplication+#endif+menuEventProcess MenuColorPicker = colorPick +menuEventProcess MenuFullScreen = fullScreen+menuEventProcess MenuAddLink = addLink+menuEventProcess MenuAddAnchor = addAnchor+menuEventProcess MenuListAnchors = listAnchors+menuEventProcess MenuEmbedPredefinedImage = embedPredefinedImage +menuEventProcess MenuEmbedPredefinedImage2 = embedPredefinedImage2 +menuEventProcess MenuEmbedPredefinedImage3 = embedPredefinedImage3 +menuEventProcess MenuApplyToAllPages = do + xst <- get + let bsty = view backgroundStyle xst+ uhdl = view (unitHoodles.currentUnit) xst+ hdl = getHoodle uhdl+ pgs = view gpages hdl + changeBkg cpage = + let cbkg = view gbackground cpage+ nbkg + | isRBkgSmpl cbkg = cbkg { rbkg_style = convertBackgroundStyleToByteString bsty }+ | otherwise = cbkg + in set gbackground nbkg cpage + npgs = fmap changeBkg pgs + nhdl = set gpages npgs hdl + modeChange ToViewAppendMode + pureUpdateUhdl (const ((hoodleModeState .~ ViewAppendState nhdl) uhdl))+ invalidateAll +menuEventProcess MenuEmbedAllPDFBkg = embedAllPDFBackground+menuEventProcess MenuTogglePanZoomWidget = togglePanZoom . view (unitHoodles.currentUnit.currentCanvas._1) =<< get +menuEventProcess MenuToggleLayerWidget = toggleLayer . view (unitHoodles.currentUnit.currentCanvas._1) =<< get +menuEventProcess MenuToggleClockWidget = toggleClock . view (unitHoodles.currentUnit.currentCanvas._1) =<< get+menuEventProcess MenuToggleScrollWidget = toggleScroll . view (unitHoodles.currentUnit.currentCanvas._1) =<< get+menuEventProcess MenuHandwritingRecognitionDialog = + handwritingRecognitionDialog >>= mapM_ (\(b,txt) -> when b $ embedHoodlet (T.unpack txt)) +menuEventProcess MenuAddTab = addTab (LocalDir Nothing)+-- menuEventProcess MenuNextTab = nextTab+menuEventProcess MenuCloseTab = closeTab+#ifdef HUB+menuEventProcess MenuEditNetEmbedTextSource = editNetEmbeddedTextSource+menuEventProcess MenuToggleNetworkEditSource = toggleNetworkEditSource+menuEventProcess MenuLaTeXNetwork = + laTeXInputNetwork Nothing (laTeXHeader <> "\n\n" <> laTeXFooter)+menuEventProcess MenuHub = hubUpload+-- menuEventProcess MenuHubSocket = socketConnect+#endif+menuEventProcess m = liftIO $ putStrLn $ "not implemented " ++ show m ++-- | +colorPick :: MainCoroutine () +colorPick = colorPickerBox "Pen Color" >>= mapM_ (\c->modify (penInfo.currentTool.penColor .~ c))++-- | +colorConvert :: Gtk.Color -> PenColor +colorConvert (Gtk.Color r g b) = ColorRGBA (realToFrac r/65536.0) (realToFrac g/65536.0) (realToFrac b/65536.0) 1.0 +-- | +colorPickerBox :: String -> MainCoroutine (Maybe PenColor) +colorPickerBox msg = do +#ifdef GTK3 + -- color selection dialog is incomplete in gtk3+ return Nothing+#else+ xst <- get + let pcolor = view (penInfo.currentTool.penColor) xst + doIOaction (action pcolor) >> go+ where + action pcolor _evhandler = do + dialog <- Gtk.colorSelectionDialogNew msg+ csel <- Gtk.colorSelectionDialogGetColor dialog+ let (r,g,b,_a) = convertPenColorToRGBA pcolor + color = Gtk.Color (floor (r*65535.0)) (floor (g*65535.0)) (floor (b*65535.0))++ Gtk.colorSelectionSetCurrentColor csel color+ res <- Gtk.dialogRun dialog + mc <- case res of + Gtk.ResponseOk -> do + clrsel <- Gtk.colorSelectionDialogGetColor dialog + clr <- Gtk.colorSelectionGetCurrentColor clrsel + return (Just (colorConvert clr))+ _ -> return Nothing + Gtk.widgetDestroy dialog + return (UsrEv (ColorChosen mc))+ go = do r <- nextevent + case r of + ColorChosen mc -> return mc + UpdateCanvas cid -> -- this is temporary+ invalidateInBBox Nothing Efficient cid >> go+ _ -> go +#endif
src/Hoodle/Coroutine/Dialog.hs view
@@ -1,9 +1,10 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE LambdaCase #-} ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Coroutine.Dialog--- Copyright : (c) 2013 Ian-Woo Kim+-- Copyright : (c) 2013,2014 Ian-Woo Kim -- -- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>@@ -14,14 +15,15 @@ module Hoodle.Coroutine.Dialog where -import Control.Lens ((%~),view)+import Control.Applicative ((<$>),(<*>))+import Control.Lens (view) import Control.Monad.Loops import Control.Monad.State-import Graphics.UI.Gtk hiding (get,set)+import qualified Data.Foldable as F+import qualified Data.Text as T+import qualified Graphics.UI.Gtk as Gtk import System.Directory (getCurrentDirectory) -- -import Control.Monad.Trans.Crtn.Queue--- import Hoodle.Coroutine.Draw import qualified Hoodle.Script.Coroutine as S import Hoodle.Type.Coroutine@@ -32,47 +34,152 @@ -- | okMessageBox :: String -> MainCoroutine () -okMessageBox msg = modify (tempQueue %~ enqueue action) - >> waitSomeEvent (\case GotOk -> True ; _ -> False) - >> return () +okMessageBox msg = action >> waitSomeEvent (\case GotOk -> True ; _ -> False) >> return () where - action = mkIOaction $ + action = doIOaction $ \_evhandler -> do - dialog <- messageDialogNew Nothing [DialogModal]- MessageQuestion ButtonsOk msg - _res <- dialogRun dialog - widgetDestroy dialog + dialog <- Gtk.messageDialogNew Nothing [Gtk.DialogModal]+ Gtk.MessageQuestion Gtk.ButtonsOk msg + _res <- Gtk.dialogRun dialog + Gtk.widgetDestroy dialog return (UsrEv GotOk) + -- | okCancelMessageBox :: String -> MainCoroutine Bool -okCancelMessageBox msg = modify (tempQueue %~ enqueue action) - >> waitSomeEvent p >>= return . q+okCancelMessageBox msg = action >> waitSomeEvent p >>= return . q where p (OkCancel _) = True p _ = False q (OkCancel b) = b q _ = False - action = mkIOaction $ + action = doIOaction $ \_evhandler -> do - dialog <- messageDialogNew Nothing [DialogModal]- MessageQuestion ButtonsOkCancel msg - res <- dialogRun dialog + dialog <- Gtk.messageDialogNew Nothing [Gtk.DialogModal]+ Gtk.MessageQuestion Gtk.ButtonsOkCancel msg + res <- Gtk.dialogRun dialog let b = case res of - ResponseOk -> True+ Gtk.ResponseOk -> True _ -> False- widgetDestroy dialog + Gtk.widgetDestroy dialog return (UsrEv (OkCancel b)) ++-- | single line text input : almost abandoned now+textInputDialog :: String -> MainCoroutine (Maybe String) +textInputDialog msg = do + doIOaction $ \_evhandler -> do + dialog <- Gtk.messageDialogNew Nothing [Gtk.DialogModal]+ Gtk.MessageQuestion Gtk.ButtonsOkCancel msg+#ifdef GTK3+ vbox <- fmap Gtk.castToContainer (Gtk.dialogGetContentArea dialog)+ txtvw <- Gtk.textViewNew+ Gtk.containerAdd vbox txtvw +#else + vbox <- Gtk.dialogGetUpper dialog+ txtvw <- Gtk.textViewNew+ Gtk.boxPackStart vbox txtvw Gtk.PackGrow 0 +#endif+ Gtk.widgetShowAll dialog+ res <- Gtk.dialogRun dialog + case res of + Gtk.ResponseOk -> do + buf <- Gtk.textViewGetBuffer txtvw + (istart,iend) <- (,) <$> Gtk.textBufferGetStartIter buf+ <*> Gtk.textBufferGetEndIter buf+ l <- Gtk.textBufferGetText buf istart iend True+ Gtk.widgetDestroy dialog+ return (UsrEv (TextInput (Just l)))+ _ -> do + Gtk.widgetDestroy dialog+ return (UsrEv (TextInput Nothing))+ TextInput input <- waitSomeEvent (\case TextInput _ -> True ; _ -> False)+ return input +++ -- | -fileChooser :: FileChooserAction -> Maybe String -> MainCoroutine (Maybe FilePath) +keywordDialog :: [T.Text] -> MainCoroutine (Maybe T.Text)+keywordDialog keylst = do+ doIOaction (keywordDialog' keylst)+ keywordLoop++-- |+keywordDialog' :: [T.Text] -> (AllEvent -> IO ()) -> IO AllEvent+keywordDialog' keys = \_evhandler -> do+ dialog <- Gtk.dialogNew+#ifdef GTK3+ upper <- fmap Gtk.castToContainer (Gtk.dialogGetContentArea dialog)+ vbox <- Gtk.vBoxNew False 0 + Gtk.containerAdd upper vbox+#else+ vbox <- Gtk.dialogGetUpper dialog+#endif+ hbox <- Gtk.hBoxNew False 0+ Gtk.boxPackStart vbox hbox Gtk.PackNatural 0+ _btnOk <- Gtk.dialogAddButton dialog ("Ok" :: String) Gtk.ResponseOk+ _btnCancel <- Gtk.dialogAddButton dialog ("Cancel" :: String) Gtk.ResponseCancel+ cbx <- Gtk.comboBoxNewText + klst <- mapM (Gtk.comboBoxAppendText cbx) keys+ when ((not.null) klst) $ + Gtk.comboBoxSetActive cbx (head klst)+ Gtk.boxPackStart hbox cbx Gtk.PackGrow 2+ Gtk.widgetShowAll dialog+ res <- Gtk.dialogRun dialog+ Gtk.widgetDestroy dialog+ case res of + Gtk.ResponseOk -> do+ keystr <- Gtk.comboBoxGetActiveText cbx+ (return . UsrEv . Keyword) keystr+ Gtk.ResponseCancel -> return (UsrEv (Keyword Nothing))+ _ -> return (UsrEv (Keyword Nothing))++-- | main event loop for keyword dialog+keywordLoop :: MainCoroutine (Maybe T.Text)+keywordLoop = waitSomeEvent (\case Keyword _ -> True ; _ -> False ) >>= \(Keyword x) -> return x+++-- |+longTextMessageBox :: String -> MainCoroutine () +longTextMessageBox msg = action+ >> waitSomeEvent (\case GotOk -> True ; _ -> False) + >> return () + where + action = doIOaction $ + \_evhandler -> do + dialog <- Gtk.dialogNew++#ifdef GTK3+ upper <- fmap Gtk.castToContainer (Gtk.dialogGetContentArea dialog)+ vbox <- Gtk.vBoxNew False 0 + Gtk.containerAdd upper vbox+#else+ vbox <- Gtk.dialogGetUpper dialog+#endif+ hbox <- Gtk.hBoxNew False 0+ txtbuf <- Gtk.textBufferNew Nothing+ Gtk.textBufferSetText txtbuf msg+ txtview <- Gtk.textViewNewWithBuffer txtbuf+ vadj <- Gtk.textViewGetVadjustment txtview+ vscr <- Gtk.vScrollbarNew vadj+ Gtk.widgetSetSizeRequest txtview 400 700+ Gtk.boxPackEnd hbox vscr Gtk.PackNatural 0 + Gtk.boxPackStart hbox txtview Gtk.PackGrow 0+ Gtk.boxPackStart vbox hbox Gtk.PackGrow 0+ _btnOk <- Gtk.dialogAddButton dialog ("Ok" :: String) Gtk.ResponseOk+ Gtk.widgetShowAll dialog+ _res <- Gtk.dialogRun dialog + Gtk.widgetDestroy dialog + return (UsrEv GotOk)++-- | +fileChooser :: Gtk.FileChooserAction -> Maybe String -> MainCoroutine (Maybe FilePath) fileChooser choosertyp mfname = do mrecentfolder <- S.recentFolderHook xst <- get let rtrwin = view rootOfRootWindow xst - liftIO $ widgetQueueDraw rtrwin - - modify (tempQueue %~ enqueue (action rtrwin mrecentfolder)) >> go + liftIO $ Gtk.widgetQueueDraw rtrwin + doIOaction (action rtrwin mrecentfolder) >> go where go = do r <- nextevent case r of @@ -80,22 +187,22 @@ UpdateCanvas cid -> -- this is temporary invalidateInBBox Nothing Efficient cid >> go _ -> go - action win mrf = mkIOaction $ \_evhandler -> do - dialog <- fileChooserDialogNew Nothing (Just win) choosertyp - [ ("OK", ResponseOk) - , ("Cancel", ResponseCancel) ]+ action win mrf _evhandler = do + dialog <- Gtk.fileChooserDialogNew Nothing (Just win) choosertyp + [ ("OK", Gtk.ResponseOk) + , ("Cancel", Gtk.ResponseCancel) ] case mrf of - Just rf -> fileChooserSetCurrentFolder dialog rf - Nothing -> getCurrentDirectory >>= fileChooserSetCurrentFolder dialog - maybe (return ()) (fileChooserSetCurrentName dialog) mfname + Just rf -> Gtk.fileChooserSetCurrentFolder dialog rf + Nothing -> getCurrentDirectory >>= Gtk.fileChooserSetCurrentFolder dialog + F.mapM_ (Gtk.fileChooserSetCurrentName dialog) mfname -- !!!!!! really hackish solution !!!!!!- whileM_ (liftM (>0) eventsPending) (mainIterationDo False)+ whileM_ (liftM (>0) Gtk.eventsPending) (Gtk.mainIterationDo False) - res <- dialogRun dialog+ res <- Gtk.dialogRun dialog mr <- case res of - ResponseDeleteEvent -> return Nothing- ResponseOk -> fileChooserGetFilename dialog - ResponseCancel -> return Nothing + Gtk.ResponseDeleteEvent -> return Nothing+ Gtk.ResponseOk -> Gtk.fileChooserGetFilename dialog + Gtk.ResponseCancel -> return Nothing _ -> putStrLn "??? in fileOpen" >> return Nothing - widgetDestroy dialog+ Gtk.widgetDestroy dialog return (UsrEv (FileChosen mr))
src/Hoodle/Coroutine/Draw.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-}@@ -7,9 +8,9 @@ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Coroutine.Draw --- Copyright : (c) 2011-2014 Ian-Woo Kim+-- Copyright : (c) 2011-2015 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -20,9 +21,8 @@ -- from other packages import Control.Applicative-import Control.Concurrent--- import Control.Concurrent.STM-import Control.Lens (view,set,(^.),(%~))+import Control.Concurrent.STM (atomically, modifyTVar')+import Control.Lens import Control.Monad import Control.Monad.State import Control.Monad.Trans.Reader (runReaderT)@@ -31,13 +31,14 @@ import Data.Time.Clock import Data.Time.LocalTime import qualified Graphics.Rendering.Cairo as Cairo-import Graphics.UI.Gtk hiding (get,set)+import qualified Graphics.UI.Gtk as Gtk -- from hoodle-platform import Control.Monad.Trans.Crtn import Control.Monad.Trans.Crtn.Object import Control.Monad.Trans.Crtn.Queue import Data.Hoodle.BBox-import Graphics.Hoodle.Render.Type.Renderer+import Graphics.Hoodle.Render.Type+-- import Graphics.Hoodle.Render.Type.Renderer -- from this package import Hoodle.Accessor import Hoodle.Type.Alias@@ -48,18 +49,19 @@ import Hoodle.Type.PageArrangement import Hoodle.Type.HoodleState import Hoodle.Type.Widget+import Hoodle.Util import Hoodle.View.Draw--- import Hoodle.Widget.Clock -- --- | +-- | all event nextevent :: MainCoroutine UserEvent nextevent = do Arg DoEvent ev <- request (Res DoEvent ()) case ev of SysEv sev -> sysevent sev >> nextevent UsrEv uev -> return uev +-- | system event sysevent :: SystemEvent -> MainCoroutine () sysevent ClockUpdateEvent = do utctime <- liftIO $ getCurrentTime @@ -69,29 +71,44 @@ (h,m,s) :: (Int,Int,Int) = (,,) <$> (\x->todHour x `mod` 12) <*> todMin <*> (floor . todSec) $ ltimeofday- -- liftIO $ print (h,m,s) xst <- get - let cinfo = view currentCanvasInfo xst+ let uhdl = view (unitHoodles.currentUnit) xst+ cinfo = view currentCanvasInfo uhdl cwgts = view (unboxLens canvasWidgets) cinfo nwgts = set (clockWidgetConfig.clockWidgetTime) (h,m,s) cwgts ncinfo = set (unboxLens canvasWidgets) nwgts cinfo- put . set currentCanvasInfo ncinfo $ xst - + pureUpdateUhdl (const ((currentCanvasInfo .~ ncinfo) uhdl)) when (view (widgetConfig.doesUseClockWidget) cwgts) $ do - let cid = getCurrentCanvasId xst+ let cid = getCurrentCanvasId uhdl modify (tempQueue %~ enqueue (Right (UsrEv (UpdateCanvasEfficient cid))))- -- invalidateInBBox Nothing Efficient cid sysevent (RenderCacheUpdate (uuid, ssfc)) = do- -- liftIO $ putStrLn "RenderCacheUpdate"- modify (renderCache %~ HM.insert uuid ssfc)+ cachevar <- view renderCacheVar <$> get+ liftIO $ atomically $ modifyTVar' cachevar (HM.insert uuid ssfc) b <- ( ^. doesNotInvalidate ) <$> get when (not b) $ invalidateAll- -- -- invalidateInBBox Nothing Efficient cid -sysevent ev = liftIO $ print ev -+sysevent ev = msgShout (show ev) +-- | update flag in HoodleState when corresponding toggle UI changed +updateFlagFromToggleUI :: String -- ^ UI toggle button id+ -> Simple Lens HoodleState Bool -- ^ lens for flag + -> MainCoroutine Bool+updateFlagFromToggleUI toggleid lensforflag = do + xstate <- get + let ui = view gtkUIManager xstate + doIOaction $ \_ -> do+ agr <- Gtk.uiManagerGetActionGroups ui >>= \x ->+ case x of + [] -> error "No action group? "+ y:_ -> return y + togglea <- Gtk.actionGroupGetAction agr toggleid + >>= maybe (error "updateFlagFromToggleUI") + (return . Gtk.castToToggleAction)+ b <- Gtk.toggleActionGetActive togglea+ return (UsrEv (UIEv (UIGetFlag b)))+ UIEv (UIGetFlag b) <- + waitSomeEvent (\case UIEv (UIGetFlag _) -> True ; _ -> False) + modify (set lensforflag b) >> return b + -- | data DrawingFunctionSet = DrawingFunctionSet { singleEditDraw :: DrawingFunction SinglePage EditMode@@ -108,46 +125,48 @@ -> DrawingFunction ContinuousPage SelectMode -> MainCoroutine () invalidateGeneral cid mbbox flag drawf drawfsel drawcont drawcontsel = do - xst <- get - unboxBiAct (fsingle xst) (fcont xst) . getCanvasInfo cid $ xst+ xst <- get+ let uhdl = view (unitHoodles.currentUnit) xst+ cache <- renderCache+ unboxBiAct (fsingle cache uhdl) (fcont cache uhdl) . getCanvasInfo cid $ uhdl where - fsingle :: HoodleState -> CanvasInfo SinglePage -> MainCoroutine () - fsingle xstate cvsInfo = do + fsingle :: RenderCache -> UnitHoodle -> CanvasInfo SinglePage -> MainCoroutine () + fsingle cache uhdl cvsInfo = do let cpn = PageNum . view currentPageNum $ cvsInfo - isCurrentCvs = cid == getCurrentCanvasId xstate- epage = getCurrentPageEitherFromHoodleModeState cvsInfo (view hoodleModeState xstate)+ isCurrentCvs = cid == getCurrentCanvasId uhdl+ epage = getCurrentPageEitherFromHoodleModeState cvsInfo (view hoodleModeState uhdl)+ cvsid = view canvasId cvsInfo cvs = view drawArea cvsInfo msfc = view mDrawSurface cvsInfo - cache = view renderCache xstate case epage of Left page -> do - liftIO (unSinglePageDraw drawf cache isCurrentCvs (cvs,msfc) (cpn,page)+ liftIO (unSinglePageDraw drawf cache cvsid isCurrentCvs (cvs,msfc) (cpn,page) <$> view viewInfo <*> pure mbbox <*> pure flag $ cvsInfo ) return () Right tpage -> do - liftIO (unSinglePageDraw drawfsel cache isCurrentCvs (cvs,msfc) (cpn,tpage)+ liftIO (unSinglePageDraw drawfsel cache cvsid isCurrentCvs (cvs,msfc) (cpn,tpage) <$> view viewInfo <*> pure mbbox <*> pure flag $ cvsInfo ) return ()- fcont :: HoodleState -> CanvasInfo ContinuousPage -> MainCoroutine () - fcont xstate cvsInfo = do - let hdlmodst = view hoodleModeState xstate - isCurrentCvs = cid == getCurrentCanvasId xstate- cache = view renderCache xstate+ fcont :: RenderCache -> UnitHoodle -> CanvasInfo ContinuousPage -> MainCoroutine () + fcont cache uhdl cvsInfo = do + let hdlmodst = view hoodleModeState uhdl + isCurrentCvs = cid == getCurrentCanvasId uhdl case hdlmodst of ViewAppendState hdl -> do hdl' <- liftIO (unContPageDraw drawcont cache isCurrentCvs cvsInfo mbbox hdl flag)- put (set hoodleModeState (ViewAppendState hdl') xstate)+ pureUpdateUhdl (const ((hoodleModeState .~ ViewAppendState hdl') uhdl)) SelectState thdl -> do thdl' <- liftIO (unContPageDraw drawcontsel cache isCurrentCvs cvsInfo mbbox thdl flag)- put (set hoodleModeState (SelectState thdl') xstate) + pureUpdateUhdl (const ((hoodleModeState .~ SelectState thdl') uhdl)) -- | invalidateOther :: MainCoroutine () invalidateOther = do - xstate <- get- let currCvsId = getCurrentCanvasId xstate- cinfoMap = getCanvasInfoMap xstate+ xst <- get+ let uhdl = view (unitHoodles.currentUnit) xst+ currCvsId = getCurrentCanvasId uhdl+ cinfoMap = view cvsInfoMap uhdl keys = M.keys cinfoMap mapM_ invalidate (filter (/=currCvsId) keys) @@ -160,10 +179,11 @@ -> DrawFlag -> CanvasId -> MainCoroutine () invalidateInBBox mbbox flag cid = do - xst <- get - geometry <- liftIO $ getCanvasGeometryCvsId cid xst - invalidateGeneral cid mbbox flag - (drawSinglePage geometry) (drawSinglePageSel geometry) (drawContHoodle geometry) (drawContHoodleSel geometry)+ xst <- get + let uhdl = view (unitHoodles.currentUnit) xst+ geometry <- liftIO $ getCanvasGeometryCvsId cid uhdl+ invalidateGeneral cid mbbox flag + (drawSinglePage geometry) (drawSinglePageSel geometry) (drawContHoodle geometry) (drawContHoodleSel geometry) -- | invalidateAllInBBox :: Maybe BBox -- ^ desktop coordinate @@ -173,26 +193,35 @@ -- | invalidateAll :: MainCoroutine () -invalidateAll = invalidateAllInBBox Nothing Clear -- >> liftIO (putStrLn "The SLOW invalidateAll Called")+invalidateAll = invalidateAllInBBox Nothing Clear -- | Invalidate Current canvas invalidateCurrent :: MainCoroutine () -invalidateCurrent = invalidate . getCurrentCanvasId =<< get+invalidateCurrent = invalidate . getCurrentCanvasId . view (unitHoodles.currentUnit) =<< get -- | Drawing temporary gadgets invalidateTemp :: CanvasId -> Cairo.Surface -> Cairo.Render () -> MainCoroutine () invalidateTemp cid tempsurface rndr = do xst <- get - forBoth' unboxBiAct (fsingle xst) . getCanvasInfo cid $ xst + let uhdl = view (unitHoodles.currentUnit) xst+ forBoth' unboxBiAct (fsingle uhdl) . getCanvasInfo cid $ uhdl where - fsingle :: HoodleState -> CanvasInfo a -> MainCoroutine () - fsingle xstate cvsInfo = do + fsingle :: UnitHoodle -> CanvasInfo a -> MainCoroutine () + fsingle uhdl cvsInfo = do let canvas = view drawArea cvsInfo pnum = PageNum . view currentPageNum $ cvsInfo - geometry <- liftIO $ getCanvasGeometryCvsId cid xstate- win <- liftIO $ widgetGetDrawWindow canvas+ geometry <- liftIO $ getCanvasGeometryCvsId cid uhdl+#ifdef GTK3 + Just win <- liftIO $ Gtk.widgetGetWindow canvas+#else+ win <- liftIO $ Gtk.widgetGetDrawWindow canvas+#endif let xformfunc = cairoXform4PageCoordinate (mkXform4Page geometry pnum)- liftIO $ renderWithDrawable win $ do +#ifdef GTK3 + liftIO $ Gtk.renderWithDrawWindow win $ do +#else + liftIO $ Gtk.renderWithDrawable win $ do +#endif Cairo.setSourceSurface tempsurface 0 0 Cairo.setOperator Cairo.OperatorSource Cairo.paint @@ -207,15 +236,24 @@ -> MainCoroutine () invalidateTempBasePage cid tempsurface pnum rndr = do xst <- get - forBoth' unboxBiAct (fsingle xst) . getCanvasInfo cid $ xst + let uhdl = view (unitHoodles.currentUnit) xst+ forBoth' unboxBiAct (fsingle uhdl) . getCanvasInfo cid $ uhdl where - fsingle :: HoodleState -> CanvasInfo a -> MainCoroutine ()- fsingle xstate cvsInfo = do + fsingle :: UnitHoodle -> CanvasInfo a -> MainCoroutine ()+ fsingle uhdl cvsInfo = do let canvas = view drawArea cvsInfo- geometry <- liftIO $ getCanvasGeometryCvsId cid xstate- win <- liftIO $ widgetGetDrawWindow canvas+ geometry <- liftIO $ getCanvasGeometryCvsId cid uhdl+#ifdef GTK3 + Just win <- liftIO $ Gtk.widgetGetWindow canvas+#else+ win <- liftIO $ Gtk.widgetGetDrawWindow canvas+#endif let xformfunc = cairoXform4PageCoordinate (mkXform4Page geometry pnum)- liftIO $ renderWithDrawable win $ do +#ifdef GTK3 + liftIO $ Gtk.renderWithDrawWindow win $ do +#else + liftIO $ Gtk.renderWithDrawable win $ do +#endif Cairo.setSourceSurface tempsurface 0 0 Cairo.setOperator Cairo.OperatorSource Cairo.paint @@ -232,14 +270,29 @@ invalidateInBBox Nothing Efficient cid >> waitSomeEvent p _ -> if p r then return r else waitSomeEvent p +-- | +doIOaction_ :: IO a -> MainCoroutine ()+doIOaction_ action = do doIOaction $ \_ -> action >> return (UsrEv ActionOrdered)+ waitSomeEvent (\case ActionOrdered -> True; _ -> False );+ return () +defaultHandler :: (AllEvent -> IO ()) -> RendererEvent -> IO ()+defaultHandler evhandler (SurfaceUpdate s) = + Gtk.postGUIAsync . evhandler . SysEv . RenderCacheUpdate $ s+defaultHandler evhandler (FinishCommandFor sfcid) = + Gtk.postGUIAsync . evhandler . UsrEv . RenderEv . FinishCommand $ sfcid+++-- | order rendering routine callRenderer :: Renderer RenderEvent -> MainCoroutine () callRenderer action = do- tvar <- (^. pdfRenderQueue) <$> get + (tvarpdf,tvargen,tvarcache) <- ((,,)<$>(^. pdfRenderQueue)<*>(^. genRenderQueue)<*>(^. renderCacheVar))<$>get doIOaction $ \evhandler -> do- let handler = postGUIAsync . evhandler . SysEv . RenderCacheUpdate- UsrEv . RenderEv <$> runReaderT action (handler,tvar)-+ -- let handler (SurfaceUpdate s) = + -- Gtk.postGUIAsync . evhandler . SysEv . RenderCacheUpdate $ s+ -- handler (FinishCommandFor sfcid) =+ -- Gtk.postGUIAsync . evhandler . UsrEv . RenderEv . FinishCommand $ sfcid+ UsrEv . RenderEv <$> runReaderT action (RendererState (defaultHandler evhandler) tvarpdf tvargen tvarcache) callRenderer_ :: Renderer a -> MainCoroutine () callRenderer_ action = do
src/Hoodle/Coroutine/Eraser.hs view
@@ -1,9 +1,9 @@ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Coroutine.Eraser --- Copyright : (c) 2011-2014 Ian-Woo Kim+-- Copyright : (c) 2011-2015 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -13,10 +13,9 @@ module Hoodle.Coroutine.Eraser where import qualified Data.IntMap as IM-import Control.Lens (view,set,over)+import Control.Lens (view,set,over,(.~)) import Control.Monad.State import qualified Control.Monad.State as St--- import Graphics.UI.Gtk hiding (get,set,disconnect) -- import Data.Hoodle.Generic import Graphics.Hoodle.Render@@ -43,9 +42,9 @@ -- | eraserStart :: CanvasId -> PointerCoord - -> MainCoroutine () -eraserStart cid = commonPenStart eraserAction cid - where eraserAction _cinfo pnum geometry (x,y) = do + -> MainCoroutine ()+eraserStart cid = commonPenStart eraserAction cid >=> const (return ())+ where eraserAction _cinfo pnum geometry (x,y) _ = do itms <- rItmsInCurrLyr eraserProcess cid pnum geometry itms (x,y) @@ -60,7 +59,7 @@ eraserProcess cid pnum geometry itms (x0,y0) = do r <- nextevent xst <- get- forBoth' unboxBiAct (f r xst) . getCanvasInfo cid $ xst + forBoth' unboxBiAct (f r xst) . getCanvasInfo cid . view (unitHoodles.currentUnit) $ xst where f :: UserEvent -> HoodleState -> CanvasInfo a -> MainCoroutine () f r xstate cvsInfo = penMoveAndUpOnly r pnum geometry defact @@ -75,19 +74,18 @@ if hitState then do page <- getCurrentPageCvsId cid - let currhdl = unView . view hoodleModeState $ xstate - dim = view gdimension page+ let uhdl = view (unitHoodles.currentUnit) xstate+ currhdl = unView . view hoodleModeState $ uhdl pgnum = view currentPageNum cvsInfo currlayer = getCurrentLayer page- cache = view renderCache xstate- let (newitms,maybebbox) = St.runState (eraseHitted hittestitem) Nothing- newlayerbbox <- liftIO . updateLayerBuf cache dim maybebbox - . set gitems newitms $ currlayer + let (newitms,_maybebbox) = St.runState (eraseHitted hittestitem) Nothing+ newlayerbbox = set gitems newitms currlayer+ callRenderer_ $ updateLayerBuf cid newlayerbbox let newpagebbox = adjustCurrentLayer newlayerbbox page newhdlbbox = over gpages (IM.adjust (const newpagebbox) pgnum) currhdl newhdlmodst = ViewAppendState newhdlbbox- commit . set hoodleModeState newhdlmodst - =<< (liftIO (updatePageAll newhdlmodst xstate))+ uhdl' <- liftIO (updatePageAll newhdlmodst uhdl)+ commit $ (unitHoodles.currentUnit .~ ((hoodleModeState .~ newhdlmodst) uhdl')) xstate invalidateInBBox Nothing Efficient cid nitms <- rItmsInCurrLyr eraserProcess cid pnum geometry nitms (x,y)
src/Hoodle/Coroutine/File.hs view
@@ -6,9 +6,9 @@ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Coroutine.File --- Copyright : (c) 2011-2014 Ian-Woo Kim+-- Copyright : (c) 2011-2015 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -18,34 +18,34 @@ module Hoodle.Coroutine.File where -- from other packages-import Control.Applicative ((<$>),(<*>))-import Control.Concurrent-import Control.Lens (view,set,over,(%~), (.~))+import Control.Applicative+import Control.Lens (at,view,set,over,(.~)) import Control.Monad.State hiding (mapM,mapM_,forM_) import Control.Monad.Trans.Either import Control.Monad.Trans.Maybe (MaybeT(..))--- import Control.Monad.Trans.Reader (runReaderT)-import Data.Attoparsec (parseOnly)+import Data.Attoparsec.ByteString.Char8 (parseOnly) import Data.ByteString.Char8 as B (pack,unpack,readFile) import qualified Data.ByteString.Lazy as L import Data.Digest.Pure.MD5 (md5) import Data.Foldable (mapM_,forM_) import qualified Data.List as List import Data.Maybe-import qualified Data.IntMap as IM import Data.Time.Clock-import Filesystem.Path.CurrentOS (decodeString, encodeString) import qualified Graphics.Rendering.Cairo as Cairo-import qualified Graphics.UI.Gtk as Gtk -- hiding (get,set)+import qualified Graphics.UI.Gtk as Gtk import System.Directory import System.FilePath-import qualified System.FSNotify as FS import System.IO (hClose, hFileSize, openFile, IOMode(..)) import System.Process +#ifdef HUB+import Control.Concurrent+import qualified Control.Exception as E+import Control.Monad.Trans.Reader+import qualified Data.Text as T+import qualified Data.Text.Encoding as TE+#endif -- from hoodle-platform import Control.Monad.Trans.Crtn-import Control.Monad.Trans.Crtn.Queue --- import Data.Hoodle.BBox import Data.Hoodle.Generic import Data.Hoodle.Simple import Data.Hoodle.Select@@ -54,49 +54,55 @@ import Graphics.Hoodle.Render.Item import Graphics.Hoodle.Render.Type import Graphics.Hoodle.Render.Type.HitTest +import Hoodle.Publish.PDF (renderHoodleToPDF) import Text.Hoodle.Builder import Text.Hoodle.Migrate.FromXournal import qualified Text.Hoodlet.Parse.Attoparsec as Hoodlet import qualified Text.Xournal.Parse.Conduit as XP--- import qualified Text.Hoodlet.Parse.Attoparsec as Hoodlet -- from this package import Hoodle.Accessor import Hoodle.Coroutine.Dialog import Hoodle.Coroutine.Draw import Hoodle.Coroutine.Commit+import Hoodle.Coroutine.Layer import Hoodle.Coroutine.Minibuffer import Hoodle.Coroutine.Mode import Hoodle.Coroutine.Page import Hoodle.Coroutine.Scroll+import Hoodle.Coroutine.Select.Clipboard import Hoodle.Coroutine.TextInput--- import Hoodle.Coroutine.Window+import Hoodle.GUI.Reflect import Hoodle.ModelAction.File import Hoodle.ModelAction.Layer import Hoodle.ModelAction.Page import Hoodle.ModelAction.Select--- import Hoodle.ModelAction.Select.Transform import Hoodle.ModelAction.Window import qualified Hoodle.Script.Coroutine as S import Hoodle.Script.Hook import Hoodle.Type.Canvas import Hoodle.Type.Coroutine+import Hoodle.Type.Enum import Hoodle.Type.Event hiding (TypSVG) import Hoodle.Type.HoodleState import Hoodle.Type.PageArrangement import Hoodle.Util+#ifdef HUB+import Hoodle.Coroutine.Hub+import Hoodle.Coroutine.Hub.Common+import Hoodle.Coroutine.HubInternal+import Hoodle.Type.Hub+import Hoodle.Type.Synchronization+#endif -- import Prelude hiding (readFile,concat,mapM,mapM_) -- | askIfSave :: MainCoroutine () -> MainCoroutine () askIfSave action = do - xstate <- get - if not (view isSaved xstate)- then do - b <- okCancelMessageBox "Current canvas is not saved yet. Will you proceed without save?" - case b of - True -> action - False -> return () + uhdl <- view (unitHoodles.currentUnit) <$> get + if not (view isSaved uhdl)+ then + okCancelMessageBox "Current canvas is not saved yet. Will you proceed without save?" >>= flip when action else action -- | @@ -110,9 +116,9 @@ else action --- | get file content from xournal file and update xournal state -getFileContent :: Maybe FilePath -> MainCoroutine ()-getFileContent (Just fname) = do +-- | get file content from xournal file and update hoodle state +getFileContent :: FileStore -> MainCoroutine ()+getFileContent store@(LocalDir (Just fname)) = do xstate <- get let ext = takeExtension fname case ext of @@ -124,39 +130,75 @@ Right h -> do constructNewHoodleStateFromHoodle h ctime <- liftIO $ getCurrentTime- modify ( hoodleFileControl.hoodleFileName .~ Just fname )- modify ( hoodleFileControl.lastSavedTime .~ Just ctime )+#ifdef HUB+ -- let uhdluuid = view (unitHoodles.currentUnit.unitUUID) xstate+ msqlfile <- view (settings.sqliteFileName) <$> get+ let fileuuidbstr = view hoodleID h+ fileuuidtxt = TE.decodeUtf8 fileuuidbstr+ liftIO $ print fileuuidtxt+ mfstat <- case msqlfile of+ Nothing -> return Nothing+ Just sqlfile -> liftIO (getLastSyncStatus sqlfile fileuuidtxt)+ let mmd5 = fileSyncStatusMd5 <$> mfstat+#else + let mmd5 = Nothing +#endif + pureUpdateUhdl ( (hoodleFileControl.hoodleFileName .~ store)+ . (hoodleFileControl.lastSavedTime .~ Just ctime) + . (hoodleFileControl.syncMD5History .~ maybeToList mmd5) ) commit_ ".xoj" -> do liftIO (XP.parseXojFile fname) >>= \x -> case x of - Left str -> liftIO $ putStrLn $ "file reading error : " ++ str + Left str -> msgShout $ "file reading error : " ++ str Right xojcontent -> do hdlcontent <- liftIO $ mkHoodleFromXournal xojcontent constructNewHoodleStateFromHoodle hdlcontent ctime <- liftIO $ getCurrentTime - modify ( hoodleFileControl.hoodleFileName .~ Just fname )- modify ( hoodleFileControl.lastSavedTime .~ Just ctime ) + pureUpdateUhdl ( (hoodleFileControl.hoodleFileName .~ LocalDir Nothing)+ . (hoodleFileControl.lastSavedTime .~ Just ctime) ) commit_ ".pdf" -> do let doesembed = view (settings.doesEmbedPDF) xstate mhdl <- liftIO $ makeNewHoodleWithPDF doesembed fname case mhdl of - Nothing -> getFileContent Nothing+ Nothing -> getFileContent (LocalDir Nothing) Just hdl -> do constructNewHoodleStateFromHoodle hdl- modify ( hoodleFileControl.hoodleFileName .~ Nothing)+ pureUpdateUhdl (hoodleFileControl.hoodleFileName .~ LocalDir Nothing) commit_- _ -> getFileContent Nothing + _ -> getFileContent (LocalDir Nothing) xstate' <- get- doIOaction $ \evhandler -> do - Gtk.postGUIAsync (setTitleFromFileName xstate')- return (UsrEv ActionOrdered)- ActionOrdered <- waitSomeEvent (\case ActionOrdered -> True ; _ -> False )- return ()-getFileContent Nothing = do+ doIOaction_ $ Gtk.postGUIAsync (setTitleFromFileName xstate')+getFileContent (LocalDir Nothing) = do constructNewHoodleStateFromHoodle =<< liftIO defaultHoodle - modify ( hoodleFileControl.hoodleFileName .~ Nothing ) + pureUpdateUhdl (hoodleFileControl.hoodleFileName .~ LocalDir Nothing) commit_ +#ifdef HUB+getFileContent store@(TempDir fname) = do + -- xstate <- get+ -- let uhdluuid = view (unitHoodles.currentUnit.unitUUID) xstate+ let ext = takeExtension fname+ when (ext == ".hdl") $ do+ bstr <- liftIO $ B.readFile fname+ r <- liftIO $ checkVersionAndMigrate bstr + case r of + Left err -> liftIO $ putStrLn err+ Right h -> do + constructNewHoodleStateFromHoodle h+ ctime <- liftIO $ getCurrentTime+ let -- fileuuidbstr = view hoodleID h+ -- fileuuidtxt = TE.decodeUtf8 fileuuidbstr+ md5txt = T.pack . show . md5 . L.fromStrict $ bstr+ pureUpdateUhdl ( (hoodleFileControl.hoodleFileName .~ store)+ . (hoodleFileControl.lastSavedTime .~ Just ctime) + . (hoodleFileControl.syncMD5History .~ [md5txt] ) + )+ commit_+ xstate' <- get+ doIOaction_ $ Gtk.postGUIAsync (setTitleFromFileName xstate')+#else+getFileContent _ = return ()+#endif -- |@@ -164,32 +206,35 @@ constructNewHoodleStateFromHoodle hdl' = do callRenderer $ cnstrctRHoodle hdl' >>= return . GotRHoodle RenderEv (GotRHoodle rhdl) <- waitSomeEvent (\case RenderEv (GotRHoodle _) -> True; _ -> False)- modify (hoodleModeState .~ ViewAppendState rhdl)-+ pureUpdateUhdl (hoodleModeState .~ ViewAppendState rhdl) --- | +-- | deprecated fileNew :: MainCoroutine () -fileNew = do - getFileContent Nothing- xstate' <- get - ncvsinfo <- liftIO $ setPage xstate' 0 (getCurrentCanvasId xstate')- xstate'' <- return $ over currentCanvasInfo (const ncvsinfo) xstate'- liftIO $ setTitleFromFileName xstate''- commit xstate'' +fileNew = do + getFileContent (LocalDir Nothing)+ updateUhdl $ \uhdl -> do+ ncvsinfo <- liftIO $ setPage uhdl 0 (getCurrentCanvasId uhdl)+ return $ (currentCanvasInfo .~ ncvsinfo) uhdl+ xst <- get+ liftIO (setTitleFromFileName xst)+ commit_ invalidateAll -- | fileSave :: MainCoroutine () fileSave = do - xstate <- get - case view (hoodleFileControl.hoodleFileName) xstate of+ uhdl <- view (unitHoodles.currentUnit) <$> get+ case getHoodleFilePath uhdl of Nothing -> fileSaveAs Just filename -> do -- this is rather temporary not to make mistake if takeExtension filename == ".hdl" then do - put =<< (liftIO (saveHoodle xstate))- (S.afterSaveHook filename . rHoodle2Hoodle . getHoodle) xstate+ updateUhdl $ liftIO . saveHoodle . const uhdl + (S.afterSaveHook filename . rHoodle2Hoodle . getHoodle) uhdl+#ifdef HUB+ hubUpload+#endif else fileExtensionInvalid (".hdl","save") >> fileSaveAs -- | interleaving a monadic action between each pair of subsequent actions@@ -199,63 +244,16 @@ sequence1_ i (a:as) = a >> i >> sequence1_ i as -- | -renderjob :: RenderCache -> RHoodle -> FilePath -> IO () -renderjob cache h ofp = do - let p = maybe (error "renderjob") id $ IM.lookup 0 (view gpages h) - let Dim width height = view gdimension p - let rf x = cairoRenderOption (RBkgDrawPDF,DrawFull) cache (x,Nothing :: Maybe Xform4Page) >> return () - Cairo.withPDFSurface ofp width height $ \s -> Cairo.renderWith s $ - (sequence1_ Cairo.showPage . map rf . IM.elems . view gpages ) h ---- | fileExport :: MainCoroutine () fileExport = fileChooser Gtk.FileChooserActionSave Nothing >>= maybe (return ()) action where - action filename = + action filename = do -- this is rather temporary not to make mistake if takeExtension filename /= ".pdf" - then fileExtensionInvalid (".pdf","export") >> fileExport - else do - xstate <- get - let hdl = getHoodle xstate - cache = view renderCache xstate- liftIO (renderjob cache hdl filename) ---- | -fileStartSync :: MainCoroutine ()-fileStartSync = do - xst <- get - let mf = (,) <$> view (hoodleFileControl.hoodleFileName) xst <*> view (hoodleFileControl.lastSavedTime) xst - maybe (return ()) (\(filename,lasttime) -> action filename lasttime) mf - where - action filename _lasttime = do - let ioact = mkIOaction $ \evhandler ->do - forkIO $ do - FS.withManager $ \wm -> do - origfile <- canonicalizePath filename - let (filedir,_) = splitFileName origfile- print filedir - _ <- FS.watchDir wm (decodeString filedir) (const True) $ \ev -> do- let mchangedfile = case ev of - FS.Added fp _ -> Just (encodeString fp)- FS.Modified fp _ -> Just (encodeString fp)- FS.Removed _fp _ -> Nothing - print mchangedfile - case mchangedfile of - Nothing -> return ()- Just changedfile -> do - let changedfilename = takeFileName changedfile - changedfile' = (filedir </> changedfilename)- if changedfile' == origfile - then do - ctime <- getCurrentTime - evhandler (UsrEv (Sync ctime))- else return () -- let sec = 1000000- forever (threadDelay (100 * sec))- return (UsrEv ActionOrdered)- modify (tempQueue %~ enqueue ioact) + then fileExtensionInvalid (".pdf","export") >> fileExport + else do + hdl <- rHoodle2Hoodle . getHoodle . view (unitHoodles.currentUnit) <$> get+ liftIO (renderHoodleToPDF hdl filename) -- | need to be merged with ContextMenuEventSVG exportCurrentPageAsSVG :: MainCoroutine ()@@ -266,25 +264,27 @@ if takeExtension filename /= ".svg" then fileExtensionInvalid (".svg","export") >> exportCurrentPageAsSVG else do- cache <- view renderCache <$> get+ cvsid <- getCurrentCanvasId . view (unitHoodles.currentUnit) <$> get+ cache <- renderCache cpg <- getCurrentPageCurr let Dim w h = view gdimension cpg liftIO $ Cairo.withSVGSurface filename w h $ \s -> Cairo.renderWith s $ - cairoRenderOption (InBBoxOption Nothing) cache (InBBox cpg,Nothing :: Maybe Xform4Page) >> return ()+ cairoRenderOption (InBBoxOption Nothing) cache cvsid (InBBox cpg,Nothing :: Maybe Xform4Page) >> return () -- | -fileLoad :: FilePath -> MainCoroutine () -fileLoad filename = do- getFileContent (Just filename)- xstate <- get - ncvsinfo <- liftIO $ setPage xstate 0 (getCurrentCanvasId xstate)- xstateNew <- return $ over currentCanvasInfo (const ncvsinfo) xstate- put . set isSaved True $ xstateNew - let ui = view gtkUIManager xstateNew- liftIO $ toggleSave ui False- liftIO $ setTitleFromFileName xstateNew +fileLoad :: FileStore -> MainCoroutine () +fileLoad filestore = do+ getFileContent filestore+ updateUhdl $ \uhdl -> do + ncvsinfo <- liftIO $ setPage uhdl 0 (getCurrentCanvasId uhdl)+ return . (currentCanvasInfo .~ ncvsinfo) . (isSaved .~ True) $ uhdl+ xst <- get + let ui = view gtkUIManager xst+ liftIO $ reflectUIToggle ui "SAVEA" False+ liftIO $ setTitleFromFileName xst clearUndoHistory modeChange ToViewAppendMode + canvasZoomUpdateAll resetHoodleBuffers invalidateAll applyActionToAllCVS adjustScrollbarWithGeometryCvsId@@ -292,78 +292,75 @@ -- | resetHoodleBuffers :: MainCoroutine () resetHoodleBuffers = do - liftIO $ putStrLn "resetHoodleBuffers called"- xst <- get - nhdlst <- liftIO $ resetHoodleModeStateBuffers - (view renderCache xst)- (view hoodleModeState xst)- let nxst = set hoodleModeState nhdlst xst- put nxst + updateUhdl $ \uhdl -> do + let hdlst = view hoodleModeState uhdl+ cvsid = getCurrentCanvasId uhdl+ callRenderer_ $ resetHoodleModeStateBuffers cvsid hdlst+ return . (hoodleModeState .~ hdlst) $ uhdl + -- | main coroutine for open a file fileOpen :: MainCoroutine () fileOpen = do mfilename <- fileChooser Gtk.FileChooserActionOpen Nothing- forM_ mfilename fileLoad + forM_ mfilename (fileLoad . LocalDir . Just) -- | main coroutine for save as fileSaveAs :: MainCoroutine () fileSaveAs = do - xstate <- get - let hdl = (rHoodle2Hoodle . getHoodle) xstate- maybe (defSaveAsAction xstate hdl) (\f -> liftIO (f hdl))- (hookSaveAsAction xstate) + hdl <- (rHoodle2Hoodle . getHoodle . view (unitHoodles.currentUnit)) <$> get+ maybe (defSaveAsAction hdl) (\f -> liftIO (f hdl)) =<< hookSaveAsAction where - hookSaveAsAction xstate = do - hset <- view hookSet xstate- saveAsHook hset- defSaveAsAction xstate hdl = do - let msuggestedact = view hookSet xstate >>= fileNameSuggestionHook - (msuggested :: Maybe String) <- maybe (return Nothing) (liftM Just . liftIO) msuggestedact + hookSaveAsAction = (saveAsHook <=< view hookSet) <$> get+ msuggestedact = (fileNameSuggestionHook <=< view hookSet) <$> get+ defSaveAsAction hdl = do + (msuggested :: Maybe String) <- maybe (return Nothing) (liftM Just . liftIO) =<< msuggestedact mr <- fileChooser Gtk.FileChooserActionSave msuggested - maybe (return ()) (action xstate hdl) mr - where action xst' hd filename = + maybe (return ()) (action hdl) mr + where action hd filename = if takeExtension filename /= ".hdl" then fileExtensionInvalid (".hdl","save") else do - askIfOverwrite filename $ do - let ntitle = B.pack . snd . splitFileName $ filename - (hdlmodst',hdl') = case view hoodleModeState xst' of- ViewAppendState hdlmap -> - if view gtitle hdlmap == "untitled"- then ( ViewAppendState . set gtitle ntitle- $ hdlmap- , (set title ntitle hd))- else (ViewAppendState hdlmap,hd)- SelectState thdl -> - if view gselTitle thdl == "untitled"- then ( SelectState $ set gselTitle ntitle thdl - , set title ntitle hd) - else (SelectState thdl,hd)- xstateNew = set (hoodleFileControl.hoodleFileName) (Just filename) - . set hoodleModeState hdlmodst' $ xst'- liftIO . L.writeFile filename . builder $ hdl'- put . set isSaved True $ xstateNew - let ui = view gtkUIManager xstateNew- liftIO $ toggleSave ui False- liftIO $ setTitleFromFileName xstateNew - S.afterSaveHook filename hdl'- + askIfOverwrite filename $ do+ updateUhdl $ \uhdl -> do+ let ntitle = B.pack . snd . splitFileName $ filename + (hdlmodst',hdl') = case view hoodleModeState uhdl of+ ViewAppendState hdlmap -> + if view gtitle hdlmap == "untitled"+ then ( ViewAppendState . set gtitle ntitle+ $ hdlmap+ , (set title ntitle hd))+ else (ViewAppendState hdlmap,hd)+ SelectState thdl -> + if view gselTitle thdl == "untitled"+ then ( SelectState $ set gselTitle ntitle thdl + , set title ntitle hd) + else (SelectState thdl,hd)+ liftIO . L.writeFile filename . builder $ hdl'+ return . (hoodleFileControl.hoodleFileName .~ LocalDir (Just filename))+ . (hoodleModeState .~ hdlmodst') + . (isSaved .~ True)+ $ uhdl+ xst <- get+ let ui = view gtkUIManager xst+ hdl'' = (rHoodle2Hoodle . getHoodle . view (unitHoodles.currentUnit)) xst+ liftIO $ reflectUIToggle ui "SAVEA" False+ liftIO $ setTitleFromFileName xst+ S.afterSaveHook filename hdl''+#ifdef HUB+ hubUpload +#endif -- | main coroutine for open a file fileReload :: MainCoroutine ()-fileReload = do - xstate <- get- case view (hoodleFileControl.hoodleFileName) xstate of - Nothing -> return () - Just filename -> do- if not (view isSaved xstate) - then do- b <- okCancelMessageBox "Discard changes and reload the file?" - case b of - True -> fileLoad filename - False -> return ()- else fileLoad filename+fileReload = do+ uhdl <- view (unitHoodles.currentUnit) <$> get+ let filestore = view (hoodleFileControl.hoodleFileName) uhdl+ if not (view isSaved uhdl) + then do+ b <- okCancelMessageBox "Discard changes and reload the file?" + when b (fileLoad filestore)+ else fileLoad filestore -- | fileExtensionInvalid :: (String,String) -> MainCoroutine ()@@ -387,11 +384,10 @@ mhdl <- liftIO $ makeNewHoodleWithPDF doesembed filename flip (maybe warning) mhdl $ \hdl -> do constructNewHoodleStateFromHoodle hdl- modify ( hoodleFileControl.hoodleFileName .~ Nothing)+ pureUpdateUhdl (hoodleFileControl.hoodleFileName .~ LocalDir Nothing) commit_ setTitleFromFileName_ canvasZoomUpdateAll- -- invalidateAll -- | set frame title according to file name@@ -427,11 +423,45 @@ fileLoadPNGorJPG = do fileChooser Gtk.FileChooserActionOpen Nothing >>= maybe (return ()) embedImage ++-- | +fileLoadImageBackground :: MainCoroutine ()+fileLoadImageBackground = do + fileChooser Gtk.FileChooserActionOpen Nothing >>= maybe (return ()) action+ where + action filename = do + xst <- get+ let fDoesEmbedImg = view (settings.doesEmbedImage) xst+ uhdl = view (unitHoodles.currentUnit) xst+ hdl = getHoodle uhdl+ Dim pw _ph = (view gdimension . fromJust . view (gpages.at 0)) hdl ++ itm <- if fDoesEmbedImg + then checkEmbedImageSize filename + >>= maybe (liftIO $ makeNewItemImage True filename) + (liftIO . makeNewItemImage True)+ else liftIO (makeNewItemImage False filename)+ let ItemImage img = itm+ Dim w h = img_dim img+ ratio = h/w + ndim = Dim pw (pw*ratio)+ img' = img { img_dim = ndim }+ changePage (const 0)+ newPage (Just ndim) PageBefore+ callRenderer $ cnstrctRItem (ItemImage img') >>= return . GotRItem + RenderEv (GotRItem nitm) <- waitSomeEvent (\case RenderEv (GotRItem _) -> True ; _ -> False)+ insertItemAt (Just (PageNum 0, PageCoord (0,0))) nitm+ modeChange ToViewAppendMode+ makeNewLayer++ embedImage :: FilePath -> MainCoroutine () embedImage filename = do - xst <- get + xst <- get+ let fDoesEmbedImg = view (settings.doesEmbedImage) xst+ uhdl = view (unitHoodles.currentUnit) xst nitm <- - if view (settings.doesEmbedImage) xst+ if fDoesEmbedImg then do mf <- checkEmbedImageSize filename --@@ -445,7 +475,7 @@ RenderEv (GotRItem r) <- waitSomeEvent (\case RenderEv (GotRItem _) -> True ; _ -> False ) return r - let cpn = view (currentCanvasInfo . unboxLens currentPageNum) xst+ let cpn = view (currentCanvasInfo . unboxLens currentPageNum) uhdl my <- autoPosText let mpos = (\y->(PageNum cpn,PageCoord (50,y)))<$>my insertItemAt mpos nitm @@ -457,11 +487,12 @@ fileChooser Gtk.FileChooserActionOpen Nothing >>= maybe (return ()) action where action filename = do - xstate <- get - liftIO $ putStrLn filename + xst <- get bstr <- liftIO $ B.readFile filename - let pgnum = view (currentCanvasInfo . unboxLens currentPageNum) xstate- hdl = getHoodle xstate + let uhdl = view (unitHoodles.currentUnit) xst+ cvsid = getCurrentCanvasId uhdl+ pgnum = view (currentCanvasInfo . unboxLens currentPageNum) uhdl+ hdl = getHoodle uhdl currpage = getPageFromGHoodleMap pgnum hdl currlayer = getCurrentLayer currpage --@@ -472,14 +503,14 @@ let otheritems = view gitems currlayer let ntpg = makePageSelectMode currpage (otheritems :- (Hitted [newitem]) :- Empty) modeChange ToSelectMode - nxstate <- get - let cache = view renderCache nxstate- thdl <- case view hoodleModeState nxstate of- SelectState thdl' -> return thdl'- _ -> (lift . EitherT . return . Left . Other) "fileLoadSVG"- nthdl <- liftIO $ updateTempHoodleSelectIO cache thdl ntpg pgnum - put ( ( set hoodleModeState (SelectState nthdl) - . set isOneTimeSelectMode YesAfterSelect) nxstate)+ updateUhdl $ \uhdl' -> do+ thdl <- case view hoodleModeState uhdl' of+ SelectState thdl' -> return thdl'+ _ -> (lift . EitherT . return . Left . Other) "fileLoadSVG"+ nthdl <- updateTempHoodleSelectM cvsid thdl ntpg pgnum + return . (hoodleModeState .~ SelectState nthdl)+ . (isOneTimeSelectMode .~ YesAfterSelect) $ uhdl'+ commit_ invalidateAll -- |@@ -487,7 +518,7 @@ askQuitProgram = do b <- okCancelMessageBox "Current canvas is not saved yet. Will you close hoodle?" case b of - True -> liftIO Gtk.mainQuit+ True -> doIOaction_ $ Gtk.postGUIAsync Gtk.mainQuit >> return (UsrEv ActionOrdered) False -> return () -- | @@ -517,11 +548,10 @@ -- | embedAllPDFBackground :: MainCoroutine () embedAllPDFBackground = do - xst <- get - let hdl = getHoodle xst+ hdl <- (rHoodle2Hoodle . getHoodle . view (unitHoodles.currentUnit)) <$> get nhdl <- liftIO . embedPDFInHoodle $ hdl- modeChange ToViewAppendMode- commit (set hoodleModeState (ViewAppendState nhdl) xst)+ constructNewHoodleStateFromHoodle nhdl+ commit_ invalidateAll -- | embed an item from hoodlet using hoodlet identifier@@ -547,11 +577,11 @@ return (md5str,name) -mkRevisionPdfFile :: RenderCache -> RHoodle -> String -> IO ()-mkRevisionPdfFile cache hdl fname = do +mkRevisionPdfFile :: Hoodle -> String -> IO ()+mkRevisionPdfFile hdl fname = do hdir <- getHomeDirectory tempfile <- mkTmpFile "pdf"- renderjob cache hdl tempfile + renderHoodleToPDF hdl tempfile let nfilename = fname <.> "pdf" vcsdir = hdir </> ".hoodle.d" </> "vcs" b <- doesDirectoryExist vcsdir @@ -561,67 +591,73 @@ -- | fileVersionSave :: MainCoroutine () fileVersionSave = do - rhdl <- getHoodle <$> get - cache <- view renderCache <$> get- let hdl = rHoodle2Hoodle rhdl+ hdl <- rHoodle2Hoodle . getHoodle . view (unitHoodles.currentUnit) <$> get rmini <- minibufDialog "Commit Message:" case rmini of Right [] -> return () Right strks' -> do doIOaction $ \_evhandler -> do (md5str,fname) <- mkRevisionHdlFile hdl- mkRevisionPdfFile cache rhdl fname+ mkRevisionPdfFile hdl fname return (UsrEv (GotRevisionInk md5str strks')) r <- waitSomeEvent (\case GotRevisionInk _ _ -> True ; _ -> False ) let GotRevisionInk md5str strks = r nrev = RevisionInk (B.pack md5str) strks- modify (\xst -> let hdlmodst = view hoodleModeState xst - in case hdlmodst of - ViewAppendState rhdl' -> - let nrhdl = over grevisions (<> [nrev]) rhdl' - in set hoodleModeState (ViewAppendState nrhdl) xst - SelectState thdl -> - let nthdl = over gselRevisions (<> [nrev]) thdl- in set hoodleModeState (SelectState nthdl) xst)+ pureUpdateUhdl $ \uhdl -> + let hdlmodst = view hoodleModeState uhdl+ in case hdlmodst of + ViewAppendState rhdl' -> + let nrhdl = over grevisions (<> [nrev]) rhdl' + in (hoodleModeState .~ ViewAppendState nrhdl) uhdl+ SelectState thdl -> + let nthdl = over gselRevisions (<> [nrev]) thdl+ in (hoodleModeState .~ SelectState nthdl) uhdl commit_ Left () -> do - txtstr <- maybe "" id <$> textInputDialog+ txtstr <- maybe "" id <$> textInputDialog "revision description" doIOaction $ \_evhandler -> do (md5str,fname) <- mkRevisionHdlFile hdl- mkRevisionPdfFile cache rhdl fname+ mkRevisionPdfFile hdl fname return (UsrEv (GotRevision md5str txtstr)) r <- waitSomeEvent (\case GotRevision _ _ -> True ; _ -> False ) let GotRevision md5str txtstr' = r nrev = Revision (B.pack md5str) (B.pack txtstr')- modify (\xst -> let hdlmodst = view hoodleModeState xst - in case hdlmodst of - ViewAppendState rhdl' -> - let nrhdl = over grevisions (<> [nrev]) rhdl' - in set hoodleModeState (ViewAppendState nrhdl) xst - SelectState thdl -> - let nthdl = over gselRevisions (<> [nrev]) thdl- in set hoodleModeState (SelectState nthdl) xst)+ pureUpdateUhdl $ \uhdl -> + let hdlmodst = view hoodleModeState uhdl+ in case hdlmodst of + ViewAppendState rhdl' -> + let nrhdl = over grevisions (<> [nrev]) rhdl' + in (hoodleModeState .~ ViewAppendState nrhdl) uhdl+ SelectState thdl -> + let nthdl = over gselRevisions (<> [nrev]) thdl+ in (hoodleModeState .~ SelectState nthdl) uhdl commit_ showRevisionDialog :: Hoodle -> [Revision] -> MainCoroutine ()-showRevisionDialog hdl revs = - liftM (view renderCache) get >>= \cache -> - modify (tempQueue %~ enqueue (action cache)) - >> waitSomeEvent (\case GotOk -> True ; _ -> False)- >> return ()+showRevisionDialog hdl revs = do+ cvsid <- getCurrentCanvasId . view (unitHoodles.currentUnit) <$> get+ cache <- renderCache+ doIOaction (action (cache,cvsid))+ waitSomeEvent (\case GotOk -> True ; _ -> False)+ return () where - action cache - = mkIOaction $ \_evhandler -> do - dialog <- Gtk.dialogNew- vbox <- Gtk.dialogGetUpper dialog- mapM_ (addOneRevisionBox cache vbox hdl) revs - _btnOk <- Gtk.dialogAddButton dialog "Ok" Gtk.ResponseOk- Gtk.widgetShowAll dialog- _res <- Gtk.dialogRun dialog- Gtk.widgetDestroy dialog- return (UsrEv GotOk)+ action (cache,cvsid) _evhandler = do + dialog <- Gtk.dialogNew+#ifdef GTK3+ upper <- fmap Gtk.castToContainer (Gtk.dialogGetContentArea dialog)+ vbox <- Gtk.vBoxNew False 0+ Gtk.containerAdd upper vbox +#else + vbox <- Gtk.dialogGetUpper dialog+#endif+ mapM_ (addOneRevisionBox cache cvsid vbox hdl) revs + _btnOk <- Gtk.dialogAddButton dialog ("Ok" :: String) Gtk.ResponseOk+ Gtk.widgetShowAll dialog+ _res <- Gtk.dialogRun dialog+ Gtk.widgetDestroy dialog+ return (UsrEv GotOk) mkPangoText :: String -> Cairo.Render ()@@ -630,7 +666,7 @@ ctxt <- Gtk.cairoCreateContext Nothing layout <- Gtk.layoutEmpty ctxt fdesc <- Gtk.fontDescriptionNew - Gtk.fontDescriptionSetFamily fdesc "Sans Mono"+ Gtk.fontDescriptionSetFamily fdesc ("Sans Mono" :: String) Gtk.fontDescriptionSetSize fdesc 8.0 Gtk.layoutSetFontDescription layout (Just fdesc) Gtk.layoutSetWidth layout (Just 250)@@ -643,19 +679,27 @@ layout <- liftIO $ pangordr rdr layout -addOneRevisionBox :: RenderCache -> Gtk.VBox -> Hoodle -> Revision -> IO ()-addOneRevisionBox cache vbox hdl rev = do +addOneRevisionBox :: RenderCache -> CanvasId -> Gtk.VBox -> Hoodle -> Revision -> IO ()+addOneRevisionBox cache cvsid vbox hdl rev = do cvs <- Gtk.drawingAreaNew cvs `Gtk.on` Gtk.sizeRequest $ return (Gtk.Requisition 250 25) cvs `Gtk.on` Gtk.exposeEvent $ Gtk.tryEvent $ do +#ifdef GTK3 + Just drawwdw <- liftIO $ Gtk.widgetGetWindow cvs +#else drawwdw <- liftIO $ Gtk.widgetGetDrawWindow cvs +#endif+#ifdef GTK3+ liftIO . Gtk.renderWithDrawWindow drawwdw $ do+#else liftIO . Gtk.renderWithDrawable drawwdw $ do +#endif case rev of - RevisionInk _ strks -> Cairo.scale 0.5 0.5 >> mapM_ (cairoRender cache) strks+ RevisionInk _ strks -> Cairo.scale 0.5 0.5 >> mapM_ (cairoRender cache cvsid) strks Revision _ txt -> mkPangoText (B.unpack txt) hdir <- getHomeDirectory let vcsdir = hdir </> ".hoodle.d" </> "vcs"- btn <- Gtk.buttonNewWithLabel "view"+ btn <- Gtk.buttonNewWithLabel ("view" :: String) btn `Gtk.on` Gtk.buttonPressEvent $ Gtk.tryEvent $ do files <- liftIO $ getDirectoryContents vcsdir let fstrinit = "UUID_" ++ B.unpack (view hoodleID hdl) @@ -675,14 +719,14 @@ fileShowRevisions :: MainCoroutine () fileShowRevisions = do - rhdl <- liftM getHoodle get + rhdl <- getHoodle . view (unitHoodles.currentUnit) <$> get let hdl = rHoodle2Hoodle rhdl let revs = view grevisions rhdl showRevisionDialog hdl revs fileShowUUID :: MainCoroutine () fileShowUUID = do - hdl <- liftM getHoodle get + hdl <- getHoodle . view (unitHoodles.currentUnit) <$> get let uuidstr = view ghoodleID hdl okMessageBox (B.unpack uuidstr) @@ -698,7 +742,7 @@ let fp = hoodletdir </> str <.> "hdlt" bstr <- liftIO $ B.readFile fp case parseOnly Hoodlet.hoodlet bstr of - Left err -> liftIO $ putStrLn err >> return Nothing+ Left err -> msgShout err >> return Nothing Right itm -> do -- callRenderer $ cnstrctRItem itm >>= return . GotRItem @@ -709,5 +753,45 @@ else return Nothing - +#ifdef HUB+-- |+syncFile :: MainCoroutine ()+syncFile = do + liftIO (putStrLn "syncFile called")+ xst <- get+ let uhdl = view (unitHoodles.currentUnit) xst+ hdir <- liftIO $ getHomeDirectory+ let tokfile = hdir </> ".hoodle.d" </> "token.txt"+ runMaybeT $ do+ let hdlidtxt = getHoodleID uhdl + hset <- (MaybeT . return . view hookSet) xst+ hinfo <- (MaybeT . return) (hubInfo hset)+ sqlfile <- (MaybeT . return . view (settings.sqliteFileName)) xst+ hdlfp <- MaybeT . return $ getHoodleFilePath uhdl+ mfstat <- liftIO $ getLastSyncStatus sqlfile hdlidtxt + lift $ prepareToken hinfo tokfile + lift $ doIOaction $ \evhandler -> do + forkIO $ (`E.catch` (\(e :: E.SomeException)-> print e >> return ())) $ + withHub hinfo tokfile $ \manager coojar -> do+ flip runReaderT (manager,coojar) $ do+ Just fstatServer <- sessionGetJSON (hubURL hinfo </> "sync" </> T.unpack hdlidtxt)+ let patchwork = + rsyncPatchWork hinfo hdlfp fstatServer $ do+ putStrLn "Am I called?"+ (evhandler . UsrEv . SyncFileFinished) fstatServer++ case mfstat of + Nothing -> patchwork+ Just fstat -> + if fileSyncStatusTime fstat < fileSyncStatusTime fstatServer+ then patchwork + else (liftIO . Gtk.postGUIAsync . evhandler . UsrEv . SyncFileFinished) fstat+ return (UsrEv ActionOrdered)+ SyncFileFinished nfstat <- + lift (waitSomeEvent (\case SyncFileFinished _-> True ; _ -> False ))+ liftIO $ print nfstat+ lift (updateSyncInfoAll nfstat)+ when (Just nfstat /= mfstat) (lift fileReload)+ return ()+#endif
src/Hoodle/Coroutine/HandwritingRecognition.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-}@@ -16,43 +17,36 @@ module Hoodle.Coroutine.HandwritingRecognition where -import Control.Lens (view,_1,_2,(%~))+import Control.Lens (view,_1,_2) import Control.Monad ((<=<),guard,when)-import Control.Monad.State (modify) import Control.Monad.Trans (liftIO) import Control.Monad.Trans.Either import Data.Aeson as A--- import Data.Aeson.Encode--- import Data.Aeson.Encode.Pretty-import qualified Data.Attoparsec as AP--- import Data.Attoparsec.Number+import qualified Data.Attoparsec.ByteString.Char8 as AP import qualified Data.ByteString.Char8 as B import qualified Data.ByteString.Lazy.Char8 as LB import Data.Foldable (mapM_) import qualified Data.HashMap.Strict as HM import qualified Data.List as L (lookup) import Data.Maybe--- import Data.Scientific import Data.Strict.Tuple import qualified Data.Text as T import Data.Traversable (forM) import Data.UUID.V4 import Data.Vector hiding (map,head,null,(++),take,modify,mapM_,zip,forM)-import Graphics.UI.Gtk +import qualified Graphics.UI.Gtk as Gtk import System.Directory import System.Exit import System.FilePath import System.Process -- -import Control.Monad.Trans.Crtn.Queue import Data.Hoodle.Simple -- from this package--- import Hoodle.Coroutine.Dialog import Hoodle.Coroutine.Draw (waitSomeEvent) import Hoodle.Coroutine.Minibuffer import Hoodle.Type.Coroutine import Hoodle.Type.Event-import Hoodle.Type.HoodleState+import Hoodle.Util -- import Prelude hiding (fst,snd,mapM_) @@ -66,7 +60,6 @@ handwritingRecognitionDialog :: MainCoroutine (Maybe (Bool,T.Text)) handwritingRecognitionDialog = do- liftIO $ putStrLn "handwriting recognition test here" r <- minibufDialog "test handwriting recognition" case r of Left err -> liftIO $ putStrLn (show err) >> return Nothing @@ -76,8 +69,7 @@ let bstr = (encode . mkAesonInk) strks let fp = tdir </> show uuid <.> "json" liftIO $ LB.writeFile fp bstr- (excode,gresult,gerror) <- liftIO $ readProcessWithExitCode "curl" ["-X", "POST", "-H", "Content-Type: application/json ", "--data-ascii", "@"++fp, "http://inputtools.google.com/request?itc=en-t-i0-handwrit&app=chext" ] ""- -- let ev0 = AP.parseOnly json (B.pack gresult) + (excode,gresult,gerror) <- liftIO $ readProcessWithExitCode "curl" ["-X", "POST", "-H", "Content-Type: application/json ", "--data-ascii", "@"++fp, "http://inputtools.google.com/request?itc=en-t-i0-handwrit" ] "" case excode of ExitSuccess -> do r_parse <- runEitherT $ do @@ -91,15 +83,15 @@ (return . mapMaybe f . toList) v4 case r_parse of - Left err -> liftIO $ putStrLn err >> return Nothing + Left err -> msgShout ("handwritingRecognitionDialog: " ++ err) >> return Nothing Right lst -> showRecogTextDialog lst - _ -> liftIO $ print gerror >> return Nothing + _ -> msgShout ("handwritingRecognitionDialog: " ++ gerror) >> return Nothing showRecogTextDialog :: [T.Text] -> MainCoroutine (Maybe (Bool,T.Text)) showRecogTextDialog txts = do - modify (tempQueue %~ enqueue action) + doIOaction action >> waitSomeEvent (\case OkCancel _ -> True GotRecogResult _ _ -> True _ -> False)@@ -107,9 +99,15 @@ GotRecogResult b txt -> return (Just (b,txt)) _ -> return Nothing where - action = mkIOaction $ \evhandler -> do - dialog <- dialogNew- vbox <- dialogGetUpper dialog+ action = \evhandler -> do + dialog <- Gtk.dialogNew+#ifdef GTK3+ upper <- fmap Gtk.castToContainer (Gtk.dialogGetContentArea dialog)+ vbox <- Gtk.vBoxNew False 0 + Gtk.containerAdd upper vbox+#else+ vbox <- Gtk.dialogGetUpper dialog+#endif let txtlst' = zip [1..] txts txtlst <- forM txtlst' $ \(n,txt) -> do let str = T.unpack txt @@ -122,26 +120,27 @@ else doesFileExist (hoodletdir </> str <.> "hdlt") return (n,(b2,txt)) mapM_ (addOneTextBox evhandler dialog vbox) txtlst - _btnCancel <- dialogAddButton dialog "Cancel" ResponseCancel- widgetShowAll dialog- res <- dialogRun dialog- widgetDestroy dialog+ _btnCancel <- Gtk.dialogAddButton dialog ("Cancel" :: String) Gtk.ResponseCancel+ Gtk.widgetShowAll dialog+ res <- Gtk.dialogRun dialog+ Gtk.widgetDestroy dialog case res of - ResponseUser n -> case L.lookup n txtlst of+ Gtk.ResponseUser n -> case L.lookup n txtlst of Nothing -> return (UsrEv (OkCancel False)) Just (b,txt) -> return (UsrEv (GotRecogResult b txt)) _ -> return (UsrEv (OkCancel False)) -addOneTextBox :: (AllEvent -> IO ()) -> Dialog -> VBox -> (Int,(Bool,T.Text)) -> IO ()+addOneTextBox :: (AllEvent -> IO ()) -> Gtk.Dialog -> Gtk.VBox + -> (Int,(Bool,T.Text)) -> IO () addOneTextBox _evhandler dialog vbox (n,(b,txt)) = do- btn <- buttonNewWithLabel (T.unpack txt)+ btn <- Gtk.buttonNewWithLabel (T.unpack txt) when b $ do - widgetModifyBg btn StateNormal (Color 60000 60000 30000)- widgetModifyBg btn StatePrelight (Color 63000 63000 40000)- widgetModifyBg btn StateActive (Color 45000 45000 18000)- btn `on` buttonPressEvent $ tryEvent $ do- liftIO $ dialogResponse dialog (ResponseUser n)- boxPackStart vbox btn PackNatural 0 + Gtk.widgetModifyBg btn Gtk.StateNormal (Gtk.Color 60000 60000 30000)+ Gtk.widgetModifyBg btn Gtk.StatePrelight (Gtk.Color 63000 63000 40000)+ Gtk.widgetModifyBg btn Gtk.StateActive (Gtk.Color 45000 45000 18000)+ btn `Gtk.on` Gtk.buttonPressEvent $ Gtk.tryEvent $ do+ liftIO $ Gtk.dialogResponse dialog (Gtk.ResponseUser n)+ Gtk.boxPackStart vbox btn Gtk.PackNatural 0 mkAesonInk :: [Stroke] -> Value mkAesonInk strks =
src/Hoodle/Coroutine/Highlighter.hs view
@@ -17,11 +17,8 @@ import Hoodle.Type.Canvas import Hoodle.Coroutine.Pen -import Control.Monad.Trans- -- | -highlighterStart :: CanvasId -> PointerCoord -> MainCoroutine () -highlighterStart cid pcoord = do - liftIO $ putStrLn "highlighter started"- penStart cid pcoord+highlighterStart :: CanvasId -> PointerCoord + -> MainCoroutine (Maybe (Maybe (Maybe ())))+highlighterStart cid pcoord = penStart cid pcoord
+ src/Hoodle/Coroutine/Hub.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}++-----------------------------------------------------------------------------+-- |+-- Module : Hoodle.Coroutine.Hub+-- Copyright : (c) 2014,2015 Ian-Woo Kim+--+-- License : BSD3+-- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>+-- Stability : experimental+-- Portability : GHC+--+-----------------------------------------------------------------------------++module Hoodle.Coroutine.Hub where++import Control.Applicative+import Control.Lens (view)+import Control.Monad.IO.Class+import Control.Monad.State+import Control.Monad.Trans.Maybe+import System.Directory+import System.FilePath (makeRelative)+--+import Hoodle.Coroutine.HubInternal+import Hoodle.Coroutine.Dialog+import Hoodle.Script.Hook+import Hoodle.Type.Coroutine+import Hoodle.Type.Hub+import Hoodle.Type.HoodleState+--++-- |+hubUpload :: MainCoroutine ()+hubUpload = do+ xst <- get+ uhdl <- view (unitHoodles.currentUnit) <$> get+ if not (view isSaved uhdl) + then + okMessageBox "hub action can be done only after saved" >> return ()+ else do r <- runMaybeT $ do + hset <- (MaybeT . return) $ view hookSet xst+ hinfo <- (MaybeT . return) (hubInfo hset)+ let hdir = hubFileRoot hinfo+ (canfp,mhdlfp) <- + case view (hoodleFileControl.hoodleFileName) uhdl of+ LocalDir Nothing -> MaybeT (return Nothing)+ LocalDir (Just fp) -> do + canfp <- liftIO $ canonicalizePath fp+ let relfp = makeRelative hdir canfp+ MaybeT . return . Just $ (canfp,Just relfp)+ TempDir fp -> do + canfp <- liftIO $ canonicalizePath fp+ MaybeT . return . Just $ (canfp,Nothing)+ lift (uploadWork (canfp,mhdlfp) hinfo)+ case r of + Nothing -> okMessageBox "upload not successful" >> return ()+ Just _ -> return () +
+ src/Hoodle/Coroutine/Hub/Common.hs view
@@ -0,0 +1,123 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}++-----------------------------------------------------------------------------+-- |+-- Module : Hoodle.Coroutine.Hub.Common+-- Copyright : (c) 2015 Ian-Woo Kim+--+-- License : BSD3+-- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>+-- Stability : experimental+-- Portability : GHC+--+-----------------------------------------------------------------------------++module Hoodle.Coroutine.Hub.Common where++import Control.Applicative+import Control.Monad.IO.Class+import Control.Monad.State+import Control.Monad.Trans.Reader+import Control.Monad.Trans.Resource+import Data.Aeson as AE+import qualified Data.ByteString.Lazy.Char8 as BL+import qualified Data.Foldable as F+import Data.IORef+import Data.Monoid ((<>))+import qualified Data.Text as T (Text,pack,unpack)+import Data.Text.Encoding (encodeUtf8)+import Database.Persist (getBy,entityVal)+import Database.Persist.Sqlite (runSqlite)+import Network+import Network.Google.OAuth2 ( formUrl, exchangeCode, refreshTokens+ , OAuth2Client(..), OAuth2Tokens(..))+import Network.HTTP.Client (GivesPopper)+import Network.HTTP.Conduit ( CookieJar, Manager+ , cookieJar, createCookieJar+ , httpLbs, parseUrl+ , requestHeaders+ , responseBody, responseCookieJar, withManager)+import System.Directory+import System.Exit (ExitCode(..))+import System.Info (os)+import System.Process (rawSystem)+--+--+import Hoodle.Coroutine.Dialog+import Hoodle.Type.Coroutine+import Hoodle.Type.Hub+import Hoodle.Type.Synchronization+--++-- |+streamContent :: BL.ByteString -> GivesPopper ()+streamContent lb np = do+ lbref <- newIORef lb + np (popper lbref)+ where popper lbref = do+ lbstr <- readIORef lbref+ if (not .BL.null) lbstr+ then do + let (lbstr1,lbstr2) = BL.splitAt 10240 lbstr+ writeIORef lbref lbstr2+ return (BL.toStrict lbstr1)+ else do+ return ""++-- |+prepareToken :: HubInfo -> FilePath -> MainCoroutine ()+prepareToken HubInfo {..} tokfile = do+ let client = OAuth2Client { clientId = T.unpack googleClientId, clientSecret = T.unpack googleClientSecret }+ permissionUrl = formUrl client ["email"]+ liftIO $ putStrLn "prepareToken"+ liftIO (doesFileExist tokfile) >>= \b -> unless b $ do + case os of+ "linux" -> liftIO $ rawSystem "chromium" [permissionUrl]+ "darwin" -> liftIO $ rawSystem "open" [permissionUrl]+ _ -> return ExitSuccess+ mauthcode <- textInputDialog "Please paste the verification code: "+ F.forM_ mauthcode $ \authcode -> do+ tokens <- liftIO $ exchangeCode client authcode+ liftIO $ writeFile tokfile (show tokens)++-- |+withHub :: HubInfo -> FilePath + -> (Manager -> CookieJar -> ResourceT IO a) -> IO a +withHub HubInfo {..} tokfile action = + withSocketsDo $ withManager $ \manager -> do+ let client = OAuth2Client { clientId = T.unpack googleClientId+ , clientSecret = T.unpack googleClientSecret }+ -- refresh token+ oldtok <- liftIO $ read <$> (readFile tokfile)+ newtok <- liftIO $ refreshTokens client oldtok+ liftIO $ writeFile tokfile (show newtok)+ --+ accessTok <- fmap (accessToken . read) (liftIO (readFile tokfile))+ request' <- parseUrl googleAuthURL+ let request = request' + { requestHeaders = [ ("Authorization", encodeUtf8 $ "Bearer " <> T.pack accessTok) ]+ , cookieJar = Just (createCookieJar [])+ }+ response <- httpLbs request manager+ let coojar = responseCookieJar response+ action manager coojar+++sessionGetJSON :: (FromJSON a) => + String -> ReaderT (Manager,CookieJar) (ResourceT IO) (Maybe a)+sessionGetJSON url = do+ (manager,coojar) <- ask + req' <- lift $ parseUrl url+ let req = req' + { requestHeaders = [ ("Accept", "application/json; charset=utf-8") ] + , cookieJar = Just coojar }+ res <- lift $ httpLbs req manager+ return (AE.decode (responseBody res))++-- |+getLastSyncStatus :: FilePath -> T.Text -> IO (Maybe FileSyncStatus)+getLastSyncStatus fp uuidtxt = + fmap entityVal <$> runSqlite (T.pack fp) (getBy (UniqueFileSyncStatusUUID uuidtxt))++
+ src/Hoodle/Coroutine/HubInternal.hs view
@@ -0,0 +1,315 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}++-----------------------------------------------------------------------------+-- |+-- Module : Hoodle.Coroutine.HubInternal+-- Copyright : (c) 2014, 2015 Ian-Woo Kim+--+-- License : BSD3+-- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>+-- Stability : experimental+-- Portability : GHC+--+-----------------------------------------------------------------------------++module Hoodle.Coroutine.HubInternal where++import Control.Applicative+import Control.Concurrent+import qualified Control.Exception as E+import Control.Lens (over,view,set,_2)+import Control.Monad.IO.Class+import Control.Monad.State+import Control.Monad.Trans.Maybe+import Control.Monad.Trans.Reader+import Control.Monad.Trans.Resource+import Data.Aeson as AE+import qualified Data.ByteString.Base64 as B64+import qualified Data.ByteString.Char8 as B+import qualified Data.ByteString.Lazy.Char8 as BL+import Data.Digest.Pure.MD5 (md5)+import qualified Data.Foldable as F+import qualified Data.IntMap as IM+import Data.List (find)+import qualified Data.Text as T (Text,pack,unpack)+import qualified Data.Text.Encoding as TE (encodeUtf8,decodeUtf8)+import Data.UUID+import Data.UUID.V4+import Database.Persist (upsert, getBy)+import Database.Persist.Sql (runMigration)+import Database.Persist.Sqlite (runSqlite)+import qualified Graphics.UI.Gtk as Gtk+import Network.HTTP.Conduit ( RequestBody(..), CookieJar, Manager+ , cookieJar, httpLbs, method, parseUrl+ , requestBody, responseBody)+import Network.HTTP.Types (methodPut)+import System.Directory+import System.FilePath ((</>),(<.>),makeRelative)+import System.Process (readProcessWithExitCode)+--+import Data.Hoodle.Generic+import Data.Hoodle.Simple+import Graphics.Hoodle.Render.Type.Hoodle+import Text.Hoodle.Builder (builder)+--+import Hoodle.Accessor+import Hoodle.Coroutine.Hub.Common+import Hoodle.Script.Hook+import Hoodle.Type.Coroutine+import Hoodle.Type.Event+import Hoodle.Type.Hub+import Hoodle.Type.HoodleState+import Hoodle.Type.Synchronization+--++ +uploadWork :: (FilePath,Maybe FilePath) -> HubInfo -> MainCoroutine ()+uploadWork (canfp,mhdlfp) hinfo@(HubInfo {..}) = do+ uhdl0 <- view (unitHoodles.currentUnit) <$> get+ let hdl = (rHoodle2Hoodle . getHoodle) uhdl0+ hdllbstr = builder hdl+ hdlbstr = BL.toStrict hdllbstr+ hdlmd5txt = T.pack (show (md5 hdllbstr))+ pureUpdateUhdl $ over (hoodleFileControl.syncMD5History) (hdlmd5txt:)+ uhdl <- view (unitHoodles.currentUnit) <$> get+ let synchist = view (hoodleFileControl.syncMD5History) uhdl+ uhdluuid = view unitUUID uhdl++ hdir <- liftIO $ getHomeDirectory+ msqlfile <- view (settings.sqliteFileName) <$> get+ let tokfile = hdir </> ".hoodle.d" </> "token.txt"+ prepareToken hinfo tokfile+ doIOaction $ \evhandler -> do + forkIO $ (`E.catch` (\(e :: E.SomeException)-> print e >> (Gtk.postGUIAsync . evhandler . UsrEv) (DisconnectedHub tokfile (canfp,mhdlfp) hinfo) >> return ())) $ + withHub hinfo tokfile $ \manager coojar -> do+ let uuidtxt = TE.decodeUtf8 (view hoodleID hdl)+ flip runReaderT (manager,coojar) $ do+ mfstat <- sessionGetJSON (hubURL </> "sync" </> T.unpack uuidtxt)+ liftIO $ print (mfstat :: Maybe FileSyncStatus)+ liftIO $ print synchist+ let uploading = uploadAndUpdateSync evhandler uhdluuid hinfo uuidtxt hdlbstr (canfp,mhdlfp) msqlfile+ flip (maybe uploading) ((,) <$> msqlfile <*> mfstat) $ + \(sqlfile,fstat) -> do+ me <- runSqlite (T.pack sqlfile) $ getBy (UniqueFileSyncStatusUUID (fileSyncStatusUuid fstat))+ case me of + Just _ -> do + let remotemd5saved = fileSyncStatusMd5 fstat+ if (remotemd5saved `elem` synchist ) || (Prelude.null synchist)+ then uploading+ else do + liftIO $ putStrLn ("uploadWork" ++ show remotemd5saved ++ "," ++ show synchist)+ liftIO $ evhandler (UsrEv (FileSyncFromHub uhdluuid fstat))+ Nothing -> uploading+ return (UsrEv ActionOrdered)+++uploadAndUpdateSync :: (AllEvent -> IO ()) -> UUID -> HubInfo -> T.Text -> B.ByteString + -> (FilePath,Maybe FilePath) -> Maybe FilePath + -> ReaderT (Manager,CookieJar) (ResourceT IO) ()+uploadAndUpdateSync evhandler uhdluuid hinfo uuidtxt hdlbstr (canfp,mhdlfp) msqlfile = do+ mfrsync <- sessionGetJSON (hubURL hinfo </> "file" </> T.unpack uuidtxt) + b64txt <- case mfrsync of + Nothing -> (return . TE.decodeUtf8 . B64.encode) hdlbstr+ Just frsync -> liftIO $ do+ let rsyncbstr = (B64.decodeLenient . TE.encodeUtf8 . frsync_sig) frsync+ tdir <- getTemporaryDirectory+ uuid'' <- nextRandom+ let tsigfile = tdir </> show uuid'' <.> "sig"+ tdeltafile = tdir </> show uuid'' <.> "delta"+ B.writeFile tsigfile rsyncbstr+ readProcessWithExitCode "rdiff" + ["delta", tsigfile, canfp, tdeltafile] ""+ deltabstr <- B.readFile tdeltafile + mapM_ removeFile [tsigfile,tdeltafile]+ (return . TE.decodeUtf8 . B64.encode) deltabstr+ let filecontent = toJSON FileContent { file_uuid = uuidtxt+ , file_path = T.pack <$> mhdlfp + , file_content = b64txt + , file_rsync = mfrsync + , client_uuid = T.pack (show uhdluuid)+ }+ filecontentbstr = encode filecontent+ (manager,coojar) <- ask+ request3' <- lift $ parseUrl (hubURL hinfo </> "file" </> T.unpack uuidtxt )+ let request3 = request3' { method = methodPut+ , requestBody = RequestBodyStreamChunked (streamContent filecontentbstr)+ , cookieJar = Just coojar }+ _response3 <- lift $ httpLbs request3 manager+ mfstat2 :: Maybe FileSyncStatus + <- sessionGetJSON (hubURL hinfo </> "sync" </> T.unpack uuidtxt)+ F.forM_ ((,) <$> msqlfile <*> mfstat2) $ \(sqlfile,fstat2) -> do + runSqlite (T.pack sqlfile) $ upsert fstat2 []+ liftIO $ evhandler (UsrEv (SyncInfoUpdated uhdluuid fstat2))+ return ()++-- | +initSqliteDB :: MainCoroutine ()+initSqliteDB = do+ msqlfile <- view (settings.sqliteFileName) <$> get+ F.forM_ msqlfile $ \sqlfile -> liftIO $ do+ runSqlite (T.pack sqlfile) $ runMigration $ migrateAll++-- | +updateSyncInfo :: UUID -> FileSyncStatus -> MainCoroutine ()+updateSyncInfo uuid fstat = do+ liftIO $ putStrLn "updateSyncInfo called"+ uhdlsMap <- snd . view unitHoodles <$> get+ let uhdls = IM.elems uhdlsMap+ case find (\x -> view unitUUID x == uuid) uhdls of + Nothing -> return ()+ Just uhdl -> do + let nuhdlsMap = IM.adjust (over (hoodleFileControl.syncMD5History) (fileSyncStatusMd5 fstat :) ) (view unitKey uhdl) uhdlsMap+ modify (set (unitHoodles._2) nuhdlsMap)+++-- | +updateSyncInfoAll :: FileSyncStatus -> MainCoroutine ()+updateSyncInfoAll fstat = do+ let fileuuid = fileSyncStatusUuid fstat + uhdlsMap <- snd . view unitHoodles <$> get+ let f uhdl = let fileuuid' = getHoodleID uhdl+ in if fileuuid == fileuuid' + then over (hoodleFileControl.syncMD5History) (fileSyncStatusMd5 fstat :) uhdl+ else uhdl+ nuhdlsMap = fmap f uhdlsMap+ modify (set (unitHoodles._2) nuhdlsMap)+ +-- |+fileSyncFromHub :: UUID -> FileSyncStatus -> MainCoroutine ()+fileSyncFromHub unituuid fstat = do+ liftIO $ putStrLn "fileSyncFromHub called"+ uhdlsMap <- snd . view unitHoodles <$> get+ let uhdls = IM.elems uhdlsMap+ hdir <- liftIO $ getHomeDirectory+ let tokfile = hdir </> ".hoodle.d" </> "token.txt"+ xst <- get+ runMaybeT $ do+ uhdl <- (MaybeT . return . find (\x -> view unitUUID x == unituuid)) uhdls + hdlfp <- MaybeT . return $ getHoodleFilePath uhdl + hset <- (MaybeT . return . view hookSet) xst+ hinfo <- (MaybeT . return) (hubInfo hset)+ lift $ prepareToken hinfo tokfile+ lift $ doIOaction $ \evhandler -> do + forkIO $ (`E.catch` (\(e :: E.SomeException)-> print e >> return ())) $ + withHub hinfo tokfile $ \manager coojar -> do+ flip runReaderT (manager,coojar) $+ rsyncPatchWork hinfo hdlfp fstat $+ (evhandler . UsrEv) (SyncInfoUpdated unituuid fstat)+ return (UsrEv ActionOrdered)+ return ()++-- |+rsyncPatchWork :: HubInfo -> FilePath -> FileSyncStatus + -> IO ()+ -> ReaderT (Manager,CookieJar) (ResourceT IO) ()+rsyncPatchWork hinfo hdlfile fstat action = do + (manager,coojar) <- ask+ let uuidtxt = fileSyncStatusUuid fstat+ sigtxt <- liftIO $ do + uuid' <- nextRandom+ tdir <- getTemporaryDirectory+ let sigfile = tdir </> show uuid' <.> "sig"+ readProcessWithExitCode "rdiff" ["signature", hdlfile, sigfile] ""+ bstr <- B.readFile sigfile+ return (TE.decodeUtf8 (B64.encode bstr))+ let frsync = FileRsync uuidtxt sigtxt+ frsyncjsonbstr = (encode . toJSON) frsync+ req' <- lift $ parseUrl (hubURL hinfo </> "rsyncdown" </> T.unpack uuidtxt)+ let req = req' { cookieJar = Just coojar + , requestBody = RequestBodyStreamChunked (streamContent frsyncjsonbstr)+ }+ mfcont <- lift $ AE.decode . responseBody <$> httpLbs req manager+ F.forM_ mfcont $ \fcont -> do+ let filebstr = (B64.decodeLenient . TE.encodeUtf8 . file_content) fcont + liftIO $ do + uuid' <- nextRandom+ tdir <- getTemporaryDirectory + let deltafile = tdir </> show uuid' <.> "delta"+ newfile = tdir </> show uuid' <.> "hdlnew"+ B.writeFile deltafile filebstr+ readProcessWithExitCode "rdiff" ["patch", hdlfile, deltafile, newfile] ""+ md5str <- show . md5 <$> BL.readFile newfile + when (md5str == T.unpack (fileSyncStatusMd5 fstat)) $ do+ copyFile newfile hdlfile+ mapM_ removeFile [deltafile,newfile]+ Gtk.postGUIAsync action+ +-- |+gotSyncEvent :: Bool -> UUID -> FileSyncStatus -> MainCoroutine ()+gotSyncEvent isforced unituuid fstat = do+ liftIO $ putStrLn "gotSyncEvent called"+ uhdlsMap <- snd . view unitHoodles <$> get+ let uhdls = IM.elems uhdlsMap+ let b = maybe True (const isforced) (find (\x -> view unitUUID x == unituuid) uhdls)+ when b $ fileSyncFromHub unituuid fstat++-- |+registerFile :: UUID -> (FilePath,Hoodle) -> MainCoroutine ()+registerFile uhdluuid (fp,hdl) = do + liftIO $ putStrLn "registerFile called"+ let hdlbstr = (BL.toStrict . builder) hdl+ hdir <- liftIO $ getHomeDirectory+ canfp <- liftIO $ canonicalizePath fp+ let mhdlfp = Just (makeRelative hdir canfp)+ xst <- get+ let fileuuidbstr = view hoodleID hdl+ fileuuidtxt = TE.decodeUtf8 fileuuidbstr+ let tokfile = hdir </> ".hoodle.d" </> "token.txt"+ runMaybeT $ do+ sqlfile <- (MaybeT . return . view (settings.sqliteFileName)) xst+ hset <- (MaybeT . return . view hookSet) xst+ hinfo <- (MaybeT . return) (hubInfo hset)+ lift $ prepareToken hinfo tokfile+ lift . doIOaction $ \evhandler -> do + forkIO $ (`E.catch` (\(e :: E.SomeException)-> print e)) $ + withHub hinfo tokfile $ \manager coojar -> do+ flip runReaderT (manager,coojar) $ do+ uploadAndUpdateSync evhandler uhdluuid hinfo fileuuidtxt hdlbstr (canfp,mhdlfp) (Just sqlfile)+ Just fstat <- sessionGetJSON (hubURL hinfo </> "sync" </> T.unpack fileuuidtxt)++ (liftIO . Gtk.postGUIAsync . evhandler . UsrEv) (SyncInfoUpdated uhdluuid fstat)+ return (UsrEv ActionOrdered)+ return () ++-- |+findUnitHoodleByHoodleID :: String -> MainCoroutine (Maybe UnitHoodle)+findUnitHoodleByHoodleID uuidstr = do + uhdlsMap <- snd . view unitHoodles <$> get+ let uhdls = IM.elems uhdlsMap+ muhdl = find ((== uuidstr) . B.unpack . view ghoodleID . getHoodle) uhdls + return muhdl +++++openShared :: UUID -> MainCoroutine ()+openShared uuid = do + xst <- get+ hdir <- liftIO $ getHomeDirectory+ let uuidstr = show uuid+ let tokfile = hdir </> ".hoodle.d" </> "token.txt"+ tmpfile <- liftIO $ (</> uuidstr <.> "hdl" ) <$> getTemporaryDirectory + liftIO $ writeFile tmpfile "" + runMaybeT $ do+ hset <- (MaybeT . return . view hookSet) xst+ hinfo <- (MaybeT . return) (hubInfo hset)+ lift $ prepareToken hinfo tokfile+ lift $ doIOaction $ \evhandler -> do + forkIO $ (`E.catch` (\(e :: E.SomeException)-> print e >> return ())) $ + withHub hinfo tokfile $ \manager coojar -> do+ flip runReaderT (manager,coojar) $ do+ mfstat <- sessionGetJSON (hubURL hinfo </> "sync" </> uuidstr)+ case mfstat of+ Nothing -> return ()+ Just fstat -> + rsyncPatchWork hinfo tmpfile fstat $+ (evhandler . UsrEv) (OpenTemp uuid tmpfile)+ return (UsrEv ActionOrdered)+ return ()++
+ src/Hoodle/Coroutine/HubInternal.hs-boot view
@@ -0,0 +1,67 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}++-----------------------------------------------------------------------------+-- |+-- Module : Hoodle.Coroutine.HubInternal+-- Copyright : (c) 2014 Ian-Woo Kim+--+-- License : BSD3+-- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>+-- Stability : experimental+-- Portability : GHC+--+-----------------------------------------------------------------------------++module Hoodle.Coroutine.HubInternal where++import Control.Applicative+import qualified Control.Exception as E+import Control.Lens (view)+import Control.Monad (unless)+import Control.Monad.IO.Class+import Control.Monad.State+import Control.Monad.Trans.Maybe+-- import Control.Monad.Trans.State+import Data.Aeson as AE+import qualified Data.ByteString.Base64 as B64+import qualified Data.ByteString.Char8 as B+import qualified Data.ByteString.Lazy.Char8 as BL+import qualified Data.Foldable as F+import qualified Data.HashMap.Strict as H+import qualified Data.List as L+import Data.Monoid ((<>))+import Data.Text (Text,pack,unpack)+import Data.Text.Encoding (encodeUtf8,decodeUtf8)+import Data.Time.Calendar+import Data.Time.Clock+import Data.UUID.V4+import Network+import Network.Google.OAuth2 (formUrl, exchangeCode, refreshTokens,+ OAuth2Client(..), OAuth2Tokens(..))+import Network.Google (makeRequest, doRequest)+import Network.HTTP.Conduit+import Network.HTTP.Types (methodPut)+import System.Directory+import System.Environment (getEnv)+import System.Exit (ExitCode(..))+import System.FilePath ((</>),(<.>),makeRelative)+import System.Info (os)+import System.Process (system, rawSystem,readProcessWithExitCode)+--+-- import Data.Hoodle.Generic+import Data.Hoodle.Simple+import Graphics.Hoodle.Render.Type.Hoodle+import Text.Hoodle.Builder (builder)+--+import Hoodle.Coroutine.Draw+import Hoodle.Script.Hook+import Hoodle.Type.Coroutine+import Hoodle.Type.Event+import Hoodle.Type.Hub+import Hoodle.Type.HoodleState+import Hoodle.Util+++uploadWork :: (FilePath,FilePath) -> HubInfo -> MainCoroutine ()
+ src/Hoodle/Coroutine/LaTeX.hs view
@@ -0,0 +1,100 @@+{-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TupleSections #-}++-----------------------------------------------------------------------------+-- |+-- Module : Hoodle.Coroutine.LaTeX+-- Copyright : (c) 2011-2014 Ian-Woo Kim+--+-- License : BSD3+-- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>+-- Stability : experimental+-- Portability : GHC+--+-----------------------------------------------------------------------------++module Hoodle.Coroutine.LaTeX where++import Control.Lens+import Control.Monad.Trans.Maybe+import Control.Monad.State+import Data.Function (on)+import Data.List (sortBy)+import Data.Maybe+import qualified Data.Text as T+import qualified Data.Text.Encoding as TE+-- +import Data.Hoodle.Simple+--+import Hoodle.ModelAction.Text+--++hoistMaybe :: (Monad m) => Maybe a -> MaybeT m a+hoistMaybe = MaybeT . return++getLaTeXComponentsFromHdl :: Hoodle -> [(Maybe T.Text,(Int,Double,T.Text))] +getLaTeXComponentsFromHdl hdl = + let mlatex_components = do + (pgnum,pg) <- (zip ([1..] :: [Int]) . view pages) hdl + l <- view layers pg+ i <- view items l+ case i of + ItemSVG svg -> + runMaybeT $ do+ v <- hoistMaybe (svg_command svg)+ guard (v == "latex")+ svgtextbstr <- hoistMaybe (svg_text svg)+ let (_,y) = svg_pos svg + svgtext = TE.decodeUtf8 svgtextbstr+ mk = extractKeyword svgtext+ return (mk,(pgnum,y,svgtext))+ _ -> []+ cfunc :: (Ord a,Ord b,Ord c) => (a,b,c) -> (a,b,c) -> Ordering + cfunc x y | view _1 x > view _1 y = GT+ | view _1 x < view _1 y = LT+ | otherwise = if | view _2 x > view _2 y -> GT+ | view _2 x < view _2 y -> LT+ | otherwise -> EQ+ latex_components = catMaybes mlatex_components+ sorted = sortBy (cfunc `on` snd) latex_components + in sorted++{- +updateLaTeX :: MainCoroutine ()+updateLaTeX = do+ rhdl <- getHoodle <$> get+ let hdl = rHoodle2Hoodle rhdl+ runMaybeT $ do + {- txtsrc <- -} MaybeT $ return (rhdl ^. gembeddedtext) + -- let km = getKeywordMap txtsrc+ -- liftIO $ print km+ -- let sorted = getLaTeXComponentsFromHdl hdl+ -- liftIO $ print sorted + return ()+-}++laTeXHeader :: T.Text+laTeXHeader = + "\\documentclass[a4paper]{article}\n\+ \\\usepackage[affil-it]{authblk}\n\+ \\\usepackage{xeCJK}\n\+ \\\xeCJKsetup{\n\+ \ CJKspace=true,\n\+ \ CJKecglue={}\n\+ \}\n\+ \\\usepackage{setspace}\n\+ \\\onehalfspacing\n\+ \\\usepackage{fontspec}\n\+ \\\setCJKmainfont{NanumGothic}\n\+ \\\usepackage{minted}\n\+ \\\pagestyle{empty}\n\+ \\\begin{document}\n"+++-- \\\\documentclass{article}\n\+-- \\\pagestyle{empty}\n\+-- \\\begin{document}\n+ +laTeXFooter :: T.Text+laTeXFooter = "\\end{document}\n"
src/Hoodle/Coroutine/Layer.hs view
@@ -3,9 +3,9 @@ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Coroutine.Layer --- Copyright : (c) 2011-2013 Ian-Woo Kim+-- Copyright : (c) 2011-2014 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -17,10 +17,9 @@ import Control.Monad.State import qualified Data.IntMap as M import Control.Category--- import Data.Label import Control.Lens (view,set) import Data.IORef-import Graphics.UI.Gtk hiding (get,set)+import qualified Graphics.UI.Gtk as Gtk -- import Data.Hoodle.Generic import Data.Hoodle.Zipper@@ -40,32 +39,39 @@ layerAction :: (HoodleModeState -> Int -> Page EditMode -> MainCoroutine HoodleModeState) - -> MainCoroutine HoodleState+ -> MainCoroutine UnitHoodle layerAction action = do xst <- get - forBoth' unboxBiAct (fsingle xst) . view currentCanvasInfo $ xst+ forBoth' unboxBiAct (fsingle xst) . view (unitHoodles.currentUnit.currentCanvasInfo) $ xst where fsingle xstate cvsInfo = do- let epage = getCurrentPageEitherFromHoodleModeState cvsInfo hdlmodst+ let uhdl = view (unitHoodles.currentUnit) xstate+ epage = getCurrentPageEitherFromHoodleModeState cvsInfo hdlmodst cpn = view currentPageNum cvsInfo- hdlmodst = view hoodleModeState xstate+ hdlmodst = view hoodleModeState uhdl newhdlmodst <- either (action hdlmodst cpn) (action hdlmodst cpn . hPage2RPage) epage - return =<< (liftIO (updatePageAll newhdlmodst . set hoodleModeState newhdlmodst $ xstate))+ return =<< (liftIO (updatePageAll newhdlmodst . set hoodleModeState newhdlmodst $ uhdl)) -- | makeNewLayer :: MainCoroutine () -makeNewLayer = layerAction newlayeraction >>= commit >> invalidateAll +makeNewLayer = do+ xst <- get+ commit . flip (set (unitHoodles.currentUnit)) xst =<< layerAction newlayeraction+ invalidateAll where newlayeraction hdlmodst cpn page = do + sfcid <- issueSurfaceID let lyrzipper = view glayers page - emptylyr = emptyRLayer + emptylyr = emptyRLayer sfcid nlyrzipper = appendGoLast lyrzipper emptylyr npage = set glayers nlyrzipper page return . setPageMap (M.adjust (const npage) cpn . getPageMap $ hdlmodst) $ hdlmodst gotoNextLayer :: MainCoroutine ()-gotoNextLayer = layerAction nextlayeraction >>= put >> invalidateAll +gotoNextLayer = do+ modify . set (unitHoodles.currentUnit) =<< layerAction nextlayeraction + invalidateAll where nextlayeraction hdlmodst cpn page = do let lyrzipper = view glayers page mlyrzipper = moveRight lyrzipper @@ -73,7 +79,9 @@ return . setPageMap (M.adjust (const npage) cpn . getPageMap $ hdlmodst) $ hdlmodst gotoPrevLayer :: MainCoroutine ()-gotoPrevLayer = layerAction prevlayeraction >>= put >> invalidateAll +gotoPrevLayer = do+ modify . set (unitHoodles.currentUnit) =<< layerAction prevlayeraction+ invalidateAll where prevlayeraction hdlmodst cpn page = do let lyrzipper = view glayers page mlyrzipper = moveLeft lyrzipper @@ -82,7 +90,9 @@ gotoLayerAt :: Int -> MainCoroutine ()-gotoLayerAt n = layerAction gotoaction >>= put >> invalidateAll +gotoLayerAt n = do+ modify . set (unitHoodles.currentUnit) =<< layerAction gotoaction + invalidateAll where gotoaction hdlmodst cpn page = do let lyrzipper = view glayers page mlyrzipper = moveTo n lyrzipper @@ -91,7 +101,10 @@ deleteCurrentLayer :: MainCoroutine ()-deleteCurrentLayer = layerAction deletelayeraction >>= commit >> invalidateAll +deleteCurrentLayer = do+ xst <- get+ commit . flip (set (unitHoodles.currentUnit)) xst =<< layerAction deletelayeraction+ invalidateAll where deletelayeraction hdlmodst cpn page = do let lyrzipper = view glayers page mlyrzipper = deleteCurrent lyrzipper @@ -100,27 +113,27 @@ startGotoLayerAt :: MainCoroutine () startGotoLayerAt = - forBoth' unboxBiAct fsingle . view currentCanvasInfo =<< get+ forBoth' unboxBiAct fsingle . view (unitHoodles.currentUnit.currentCanvasInfo) =<< get where fsingle cvsInfo = do xstate <- get - let hdlmodst = view hoodleModeState xstate- let epage = getCurrentPageEitherFromHoodleModeState cvsInfo hdlmodst+ let uhdl = view (unitHoodles.currentUnit) xstate+ hdlmodst = view hoodleModeState uhdl+ epage = getCurrentPageEitherFromHoodleModeState cvsInfo hdlmodst page = either id (hPage2RPage) epage lyrzipper = view glayers page cidx = currIndex lyrzipper len = lengthSZ lyrzipper lref <- liftIO $ newIORef cidx dialog <- liftIO (layerChooseDialog lref cidx len)- res <- liftIO $ dialogRun dialog+ res <- liftIO $ Gtk.dialogRun dialog case res of - ResponseDeleteEvent -> liftIO $ widgetDestroy dialog- ResponseOk -> do- liftIO $ widgetDestroy dialog+ Gtk.ResponseDeleteEvent -> liftIO $ Gtk.widgetDestroy dialog+ Gtk.ResponseOk -> do+ liftIO $ Gtk.widgetDestroy dialog newnum <- liftIO (readIORef lref)- -- liftIO $ putStrLn (show (newnum)) gotoLayerAt newnum- ResponseCancel -> liftIO $ widgetDestroy dialog+ Gtk.ResponseCancel -> liftIO $ Gtk.widgetDestroy dialog _ -> error "??? in fileOpen " return ()
src/Hoodle/Coroutine/Link.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-}@@ -8,9 +9,9 @@ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Coroutine.Link--- Copyright : (c) 2013, 2014 Ian-Woo Kim+-- Copyright : (c) 2013-2015 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -20,28 +21,32 @@ module Hoodle.Coroutine.Link where import Control.Applicative-import Control.Concurrent (forkIO)-import Control.Lens (at,view,set,(%~))-import Control.Monad (forever,void)-import Control.Monad.State (get,put,modify,liftIO,guard,when)+import Control.Lens (_2,at,view,set,(^.))+import Control.Monad hiding (forM_)+import Control.Monad.State (get,liftIO) import Control.Monad.Trans.Maybe import qualified Data.ByteString.Char8 as B import Data.Foldable (forM_)+import qualified Data.IntMap as IM import qualified Data.Map as M import Data.Maybe (mapMaybe) import Data.Monoid (mconcat) import Data.UUID.V4 (nextRandom) import qualified Data.Text as T import qualified Data.Text.Encoding as TE+import qualified Graphics.UI.Gtk as Gtk+import System.Directory+import System.FilePath +import System.Process (createProcess, proc)+#ifdef HUB+import Control.Concurrent (forkIO) import DBus import DBus.Client-import Graphics.UI.Gtk hiding (get,set) -import System.FilePath +#endif -- from hoodle-platform-import Control.Monad.Trans.Crtn.Queue import Data.Hoodle.BBox import Data.Hoodle.Generic-import Data.Hoodle.Simple -- (Anchor(..),Item(..),SVG(..),pages,layers,items)+import Data.Hoodle.Simple import Data.Hoodle.Zipper import Graphics.Hoodle.Render.Item import Graphics.Hoodle.Render.Type @@ -51,10 +56,10 @@ import Hoodle.Accessor import Hoodle.Coroutine.Dialog import Hoodle.Coroutine.Draw--- import Hoodle.Coroutine.File (insertItemAt) import Hoodle.Coroutine.Page (changePage) import Hoodle.Coroutine.Select.Clipboard import Hoodle.Coroutine.TextInput +import Hoodle.Coroutine.Window import Hoodle.Device import Hoodle.ModelAction.ContextMenu import Hoodle.ModelAction.File (makeNewItemImage)@@ -67,17 +72,49 @@ import Hoodle.Type.PageArrangement import Hoodle.Util import Hoodle.View.Coordinate+#ifdef HUB+import Hoodle.Coroutine.File+#endif -- import Prelude hiding (mapM_) +-- | +openLinkAction :: UrlPath + -> Maybe (T.Text,T.Text) -- ^ (docid,anchorid)+ -> MainCoroutine () +openLinkAction urlpath mid = do + case urlpath of + FileUrl fp -> do+ mk <- liftIO . checkPreviouslyOpenedFile fp =<< get+ case mk of + Just k -> switchTab k >> forM_ mid (uncurry goToAnchorPos)+ Nothing -> addTab (LocalDir (Just fp)) >> +#ifdef HUB+ syncFile >> +#endif+ forM_ mid (uncurry goToAnchorPos)+ HttpUrl url -> liftIO $ createProcess (proc "xdg-open" [url]) >> return () ++-- |+checkPreviouslyOpenedFile :: FilePath -> HoodleState -> IO (Maybe Int)+checkPreviouslyOpenedFile fp xst = do+ cfp <- canonicalizePath fp+ lst <- filterM (checker cfp . snd) (IM.assocs (xst ^. unitHoodles._2))+ case lst of+ x:_ -> return (Just (fst x))+ _ -> return Nothing+ where checker cfp uhdl = getHoodleFilePath uhdl # + maybe (return False) $ \fp' -> do cfp' <- canonicalizePath fp' + return (cfp == cfp') + makeTextSVGFromStringAt :: String - -> CanvasId - -> HoodleState- -> CanvasCoordinate- -> IO (B.ByteString, BBox)-makeTextSVGFromStringAt str cid xst ccoord = do + -> CanvasId + -> UnitHoodle+ -> CanvasCoordinate+ -> IO (B.ByteString, BBox)+makeTextSVGFromStringAt str cid uhdl ccoord = do rdr <- makePangoTextSVG (0,0) (T.pack str) -- for the time being, I use string - geometry <- getCanvasGeometryCvsId cid xst + geometry <- getCanvasGeometryCvsId cid uhdl let mpgcoord = (desktop2Page geometry . canvas2Desktop geometry) ccoord return $ case mpgcoord of Nothing -> rdr @@ -88,11 +125,11 @@ -- | notifyLink :: CanvasId -> PointerCoord -> MainCoroutine () notifyLink cid pcoord = do - xst <- get - (forBoth' unboxBiAct (f xst) . getCanvasInfo cid) xst + uhdl <- view (unitHoodles.currentUnit) <$> get + forBoth' unboxBiAct (f uhdl) (getCanvasInfo cid uhdl) where - f :: forall b. HoodleState -> CanvasInfo b -> MainCoroutine ()- f xst cvsInfo = do + f :: forall b. UnitHoodle -> CanvasInfo b -> MainCoroutine ()+ f uhdl cvsInfo = do let cpn = PageNum . view currentPageNum $ cvsInfo arr = view (viewInfo.pageArrangement) cvsInfo mnotifyitem = view notifiedItem cvsInfo@@ -102,7 +139,7 @@ case (desktop2Page geometry . device2Desktop geometry) pcoord of Nothing -> return Nothing Just (pnum,PageCoord (x,y)) -> do - let hdl = getHoodle xst+ let hdl = getHoodle uhdl mpage = view (gpages.at (unPageNum pnum)) hdl case mpage of Nothing -> return Nothing@@ -113,27 +150,26 @@ hitted = takeHitted hlnks case mnotifyitem of Nothing -> if ((not.null) hitted) - then Just <$> newNotify cvsInfo geometry pnum (head hitted) Nothing + then Just <$> newNotify geometry pnum (head hitted) Nothing else return Nothing Just (opnum,obbx,_) -> do let obbx_desk = xformBBox (unDeskCoord . page2Desktop geometry . (opnum,) . PageCoord) obbx if pnum == opnum && isPointInBBox obbx (x,y) then return Nothing else if ((not.null) hitted) - then Just <$> newNotify cvsInfo geometry pnum (head hitted) (Just obbx_desk)+ then Just <$> newNotify geometry pnum (head hitted) (Just obbx_desk) else return (Just (Nothing,obbx_desk)) forM_ mresult (\(mnewnotified,bbx_desk) -> do- let ncinfobox = (set (unboxLens notifiedItem) mnewnotified . getCanvasInfo cid) xst - put (setCanvasInfo (cid,ncinfobox) xst)+ let ncinfobox = (set (unboxLens notifiedItem) mnewnotified . getCanvasInfo cid) uhdl + pureUpdateUhdl $ setCanvasInfo (cid,ncinfobox) invalidateInBBox (Just bbx_desk) Efficient cid ) ---- - newNotify :: CanvasInfo a -> CanvasGeometry -> PageNum -> RItem -> Maybe BBox + newNotify :: CanvasGeometry -> PageNum -> RItem -> Maybe BBox -> MainCoroutine (Maybe (PageNum,BBox,RItem),BBox) - newNotify _cvsInfo geometry pnum lnk mobbx_desk = do + newNotify geometry pnum lnk mobbx_desk = do let bbx = getBBox lnk bbx_desk = xformBBox (unDeskCoord . page2Desktop geometry . (pnum,) . PageCoord) bbx- nbbx_desk = maybe bbx_desk (\obbx_desk->unionBBox bbx_desk obbx_desk) mobbx_desk- liftIO $ print (pnum,bbx)+ nbbx_desk = maybe bbx_desk (unionBBox bbx_desk) mobbx_desk return (Just (pnum,bbx,lnk),nbbx_desk) @@ -141,9 +177,9 @@ gotLink :: Maybe String -> (Int,Int) -> MainCoroutine () gotLink mstr (x,y) = do xst <- get - -- liftIO $ print mstr - let cid = getCurrentCanvasId xst- cache = view renderCache xst+ cache <- renderCache+ let uhdl = view (unitHoodles.currentUnit) xst + cid = getCurrentCanvasId uhdl mr <- runMaybeT $ do str <- (MaybeT . return) mstr let (str1,rem1) = break (== ',') str @@ -165,17 +201,16 @@ liftIO (makeNewItemImage isembedded file) RenderEv (GotRItem nitm) <- waitSomeEvent (\case RenderEv (GotRItem _) -> True ; _ -> False )- geometry <- liftIO $ getCanvasGeometryCvsId cid xst + geometry <- liftIO $ getCanvasGeometryCvsId cid uhdl let ccoord = CvsCoord (fromIntegral x,fromIntegral y) mpgcoord = (desktop2Page geometry . canvas2Desktop geometry) ccoord insertItemAt mpgcoord nitm else return () Just (HttpUrl url) -> do - case getSelectedItmsFromHoodleState xst of + case getSelectedItmsFromUnitHoodle uhdl of Nothing -> do uuidbstr <- liftIO $ B.pack . show <$> nextRandom - rdrbbx <- liftIO $ makeTextSVGFromStringAt url cid xst - (CvsCoord (fromIntegral x,fromIntegral y))+ rdrbbx <- liftIO $ makeTextSVGFromStringAt url cid uhdl (CvsCoord (fromIntegral x,fromIntegral y)) linkInsert "simple" (uuidbstr,url) url rdrbbx Just hititms -> do b <- okCancelMessageBox ("replace selected item with link to " ++ url ++ "?")@@ -183,24 +218,23 @@ let ulbbox = (unUnion . mconcat . fmap (Union . Middle . getBBox)) hititms case ulbbox of Middle bbox -> do - svg <- liftIO $ makeSVGFromSelection cache hititms bbox+ svg <- liftIO $ makeSVGFromSelection cache cid hititms bbox uuidbstr <- liftIO $ B.pack . show <$> nextRandom deleteSelection linkInsert "simple" (uuidbstr,url) url (svg_render svg,bbox) _ -> return () Just (uuidbstr,fp) -> do let fn = takeFileName fp - case getSelectedItmsFromHoodleState xst of + case getSelectedItmsFromUnitHoodle uhdl of Nothing -> do rdr <- liftIO (makePangoTextSVG (0,0) (T.pack fn)) - geometry <- liftIO $ getCanvasGeometryCvsId cid xst + geometry <- liftIO $ getCanvasGeometryCvsId cid uhdl let ccoord = CvsCoord (fromIntegral x,fromIntegral y) mpgcoord = (desktop2Page geometry . canvas2Desktop geometry) ccoord rdr' = case mpgcoord of Nothing -> rdr Just (_,PageCoord (x',y')) -> - let bbox' = moveBBoxULCornerTo (x',y') (snd rdr) - in (fst rdr,bbox')+ let bbox' = moveBBoxULCornerTo (x',y') (snd rdr) in (fst rdr,bbox') linkInsert "simple" (uuidbstr,fp) fn rdr' Just hititms -> do b <- okCancelMessageBox ("replace selected item with link to " ++ fn ++ "?")@@ -208,22 +242,20 @@ let ulbbox = (unUnion . mconcat . fmap (Union . Middle . getBBox)) hititms case ulbbox of Middle bbox -> do - svg <- liftIO $ makeSVGFromSelection cache hititms bbox+ svg <- liftIO $ makeSVGFromSelection cache cid hititms bbox uuid <- liftIO $ nextRandom let uuidbstr' = B.pack (show uuid) deleteSelection linkInsert "simple" (uuidbstr',fp) fn (svg_render svg,bbox) _ -> return () - liftIO $ putStrLn "gotLink"- liftIO $ print mstr - liftIO $ print (x,y) + -- | addLink :: MainCoroutine () addLink = do - mfilename <- fileChooser FileChooserActionOpen Nothing - modify (tempQueue %~ enqueue (action mfilename)) - minput <- go+ mfilename <- fileChooser Gtk.FileChooserActionOpen Nothing + doIOaction $ const (action mfilename) + AddLink minput <- waitSomeEvent (\case AddLink _ -> True; _ -> False) case minput of Nothing -> return () Just (str,fname) -> do @@ -232,60 +264,51 @@ rdr <- liftIO (makePangoTextSVG (0,0) (T.pack str)) linkInsert "simple" (uuidbstr,fname) str rdr where - go = do r <- nextevent- case r of - AddLink minput -> return minput - UpdateCanvas cid -> -- this is temporary - (invalidateInBBox Nothing Efficient cid) >> go - _ -> go - action mfn = mkIOaction $ - \_evhandler -> do - dialog <- messageDialogNew Nothing [DialogModal]- MessageQuestion ButtonsOkCancel "add link" - vbox <- dialogGetUpper dialog- txtvw <- textViewNew- boxPackStart vbox txtvw PackGrow 0 - widgetShowAll dialog- res <- dialogRun dialog + action mfn = do dialog <- Gtk.messageDialogNew Nothing [Gtk.DialogModal]+ Gtk.MessageQuestion Gtk.ButtonsOkCancel ("add link" :: String)+#ifdef GTK3 + upper <- fmap Gtk.castToContainer (Gtk.dialogGetContentArea dialog)+ vbox <- Gtk.vBoxNew False 0+ Gtk.containerAdd upper vbox+#else+ vbox <- Gtk.dialogGetUpper dialog+#endif+ txtvw <- Gtk.textViewNew+ Gtk.boxPackStart vbox txtvw Gtk.PackGrow 0 + Gtk.widgetShowAll dialog+ res <- Gtk.dialogRun dialog case res of - ResponseOk -> do - buf <- textViewGetBuffer txtvw - (istart,iend) <- (,) <$> textBufferGetStartIter buf- <*> textBufferGetEndIter buf- l <- textBufferGetText buf istart iend True- widgetDestroy dialog+ Gtk.ResponseOk -> do + buf <- Gtk.textViewGetBuffer txtvw + (istart,iend) <- (,) <$> Gtk.textBufferGetStartIter buf+ <*> Gtk.textBufferGetEndIter buf+ l <- Gtk.textBufferGetText buf istart iend True+ Gtk.widgetDestroy dialog return (UsrEv (AddLink ((l,) <$> mfn)))- _ -> do - widgetDestroy dialog- return (UsrEv (AddLink Nothing))+ _ -> Gtk.widgetDestroy dialog >> return (UsrEv (AddLink Nothing)) -- | listAnchors :: MainCoroutine ()-listAnchors = liftIO . print . getAnchorMap . rHoodle2Hoodle . getHoodle =<< get+listAnchors = msgShout . show . getAnchorMap . rHoodle2Hoodle . getHoodle . view (unitHoodles.currentUnit) =<< get getAnchorMap :: Hoodle -> M.Map T.Text (Int, (Double,Double)) getAnchorMap hdl = let pgs = view pages hdl- itemsInPage pg = do l <- view layers pg - i <- view items l - return i+ itemsInPage pg = [i | l <- view layers pg, i <- view items l ] anchorsWithPageNum :: [(Int,[Anchor])] - anchorsWithPageNum = zip [0..] - (map (mapMaybe lookupAnchor . itemsInPage) pgs)- anchormap = foldr (\(p,ys) m -> foldr (insertAnchor p) m ys) - M.empty anchorsWithPageNum- in anchormap+ anchorsWithPageNum = zip [0..] (map (mapMaybe lookupAnchor . itemsInPage) pgs)+ in foldr (\(p,ys) m -> foldr (insertAnchor p) m ys) M.empty anchorsWithPageNum -- anchormap where lookupAnchor (ItemAnchor a) = Just a lookupAnchor _ = Nothing- insertAnchor pgnum (Anchor {..}) = - M.insert (TE.decodeUtf8 anchor_id) (pgnum,anchor_pos) + insertAnchor pgnum (Anchor {..}) = M.insert (TE.decodeUtf8 anchor_id) (pgnum,anchor_pos) + -- | +#ifdef HUB startLinkReceiver :: MainCoroutine () startLinkReceiver = do - xst <- get- let callback = view callBack xst + callback <- view callBack <$> get liftIO . forkIO $ do client <- connectSession requestName client "org.ianwookim" []@@ -304,19 +327,18 @@ let r = T.splitOn "," txt case r of docid:anchorid:_ -> - (postGUISync . callback . UsrEv . DBusEv . GoToLink) + (Gtk.postGUISync . callback . UsrEv . DBusEv . GoToLink) (docid,anchorid) _ -> return () _ -> return () +#endif + goToAnchorPos :: T.Text -> T.Text -> MainCoroutine () goToAnchorPos docid anchorid = do - xst <- get- let rhdl = getHoodle xst - hdl = rHoodle2Hoodle rhdl+ rhdl <- getHoodle . view (unitHoodles.currentUnit) <$> get+ let hdl = rHoodle2Hoodle rhdl when (docid == (TE.decodeUtf8 . view ghoodleID) rhdl) $ do let anchormap = getAnchorMap hdl- forM_ (M.lookup anchorid anchormap) $ \(pgnum,(x,y))-> do- liftIO $ print (pgnum,(x,y))- changePage (const pgnum)+ forM_ (M.lookup anchorid anchormap) $ \(pgnum,_)-> changePage (const pgnum)
src/Hoodle/Coroutine/Minibuffer.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE LambdaCase #-} -----------------------------------------------------------------------------@@ -15,15 +16,14 @@ module Hoodle.Coroutine.Minibuffer where import Control.Applicative ((<$>),(<*>))-import Control.Lens ((%~),view)-import Control.Monad.State (modify,get)+import Control.Lens (view)+import Control.Monad.State (get) import Control.Monad.Trans (liftIO) import Data.Foldable (Foldable(..),mapM_,forM_,toList) import Data.Sequence (Seq,(|>),empty,singleton,viewl,ViewL(..)) import qualified Graphics.Rendering.Cairo as Cairo-import Graphics.UI.Gtk hiding (get,set)+import qualified Graphics.UI.Gtk as Gtk -- -import Control.Monad.Trans.Crtn.Queue (enqueue) import Data.Hoodle.Simple import Graphics.Hoodle.Render (renderStrk) --@@ -60,40 +60,48 @@ xst <- get let dev = view deviceList xst let ui = view gtkUIManager xst - agr <- liftIO ( uiManagerGetActionGroups ui >>= \x ->+ agr <- liftIO ( Gtk.uiManagerGetActionGroups ui >>= \x -> case x of [] -> error "No action group? " y:_ -> return y )- uxinputa <- liftIO (actionGroupGetAction agr "UXINPUTA" >>= \(Just x) -> - return (castToToggleAction x) )- doesUseX11Ext <- liftIO $ toggleActionGetActive uxinputa- modify (tempQueue %~ enqueue (action dev doesUseX11Ext)) + uxinputa <- liftIO (Gtk.actionGroupGetAction agr "UXINPUTA" >>= \(Just x) -> + return (Gtk.castToToggleAction x) )+ doesUseX11Ext <- liftIO $ Gtk.toggleActionGetActive uxinputa+ doIOaction (action dev doesUseX11Ext) minibufInit where - action dev _doesUseX11Ext = mkIOaction $ \evhandler -> do - dialog <- dialogNew - msgLabel <- labelNew (Just msg) - cvs <- drawingAreaNew - cvs `on` sizeRequest $ return (Requisition 500 50)- cvs `on` exposeEvent $ tryEvent $ do- drawwdw <- liftIO $ widgetGetDrawWindow cvs - liftIO (renderWithDrawable drawwdw drawMiniBufBkg)+ action dev _doesUseX11Ext = \evhandler -> do + dialog <- Gtk.dialogNew + msgLabel <- Gtk.labelNew (Just msg) + cvs <- Gtk.drawingAreaNew + cvs `Gtk.on` Gtk.sizeRequest $ return (Gtk.Requisition 500 50)+ cvs `Gtk.on` Gtk.exposeEvent $ Gtk.tryEvent $ do+#ifdef GTK3 + Just drawwdw <- liftIO $ Gtk.widgetGetWindow cvs+#else+ drawwdw <- liftIO $ Gtk.widgetGetDrawWindow cvs +#endif+#ifdef GTK3+ liftIO (Gtk.renderWithDrawWindow drawwdw drawMiniBufBkg)+#else+ liftIO (Gtk.renderWithDrawable drawwdw drawMiniBufBkg)+#endif (liftIO . evhandler . UsrEv . MiniBuffer . MiniBufferInitialized) drawwdw- cvs `on` buttonPressEvent $ tryEvent $ do + cvs `Gtk.on` Gtk.buttonPressEvent $ Gtk.tryEvent $ do (mbtn,mp) <- getPointer dev forM_ mp $ \p -> do let pbtn = maybe PenButton1 id mbtn case pbtn of TouchButton -> return () _ -> (liftIO . evhandler . UsrEv . MiniBuffer) (MiniBufferPenDown pbtn p)- cvs `on` buttonReleaseEvent $ tryEvent $ do + cvs `Gtk.on` Gtk.buttonReleaseEvent $ Gtk.tryEvent $ do (mbtn,mp) <- getPointer dev forM_ mp $ \p -> do let pbtn = maybe PenButton1 id mbtn case pbtn of TouchButton -> return () _ -> (liftIO . evhandler . UsrEv . MiniBuffer) (MiniBufferPenUp p)- cvs `on` motionNotifyEvent $ tryEvent $ do + cvs `Gtk.on` Gtk.motionNotifyEvent $ Gtk.tryEvent $ do (mbtn,mp) <- getPointer dev forM_ mp $ \p -> do let pbtn = maybe PenButton1 id mbtn @@ -103,23 +111,29 @@ {- if doesUseX11Ext then widgetSetExtensionEvents cvs [ExtensionEventsAll] else widgetSetExtensionEvents cvs [ExtensionEventsNone] -}- widgetAddEvents cvs [PointerMotionMask,Button1MotionMask] + Gtk.widgetAddEvents cvs [Gtk.PointerMotionMask,Gtk.Button1MotionMask] --- vbox <- dialogGetUpper dialog- hbox <- hBoxNew False 0 - boxPackStart hbox msgLabel PackNatural 0 - boxPackStart vbox hbox PackNatural 0- boxPackStart vbox cvs PackNatural 0- _btnOk <- dialogAddButton dialog "Ok" ResponseOk- _btnCancel <- dialogAddButton dialog "Cancel" ResponseCancel- _btnText <- dialogAddButton dialog "TextInput" (ResponseUser 1) - widgetShowAll dialog- res <- dialogRun dialog - widgetDestroy dialog +#ifdef GTK3+ upper <- fmap Gtk.castToContainer (Gtk.dialogGetContentArea dialog)+ vbox <- Gtk.vBoxNew False 0 + Gtk.containerAdd upper vbox+#else + vbox <- Gtk.dialogGetUpper dialog+#endif+ hbox <- Gtk.hBoxNew False 0 + Gtk.boxPackStart hbox msgLabel Gtk.PackNatural 0 + Gtk.boxPackStart vbox hbox Gtk.PackNatural 0+ Gtk.boxPackStart vbox cvs Gtk.PackNatural 0+ _btnOk <- Gtk.dialogAddButton dialog "Ok" Gtk.ResponseOk+ _btnCancel <- Gtk.dialogAddButton dialog "Cancel" Gtk.ResponseCancel+ _btnText <- Gtk.dialogAddButton dialog "TextInput" (Gtk.ResponseUser 1) + Gtk.widgetShowAll dialog+ res <- Gtk.dialogRun dialog + Gtk.widgetDestroy dialog case res of - ResponseOk -> return (UsrEv (OkCancel True))- ResponseCancel -> return (UsrEv (OkCancel False))- ResponseUser 1 -> return (UsrEv ChangeDialog)+ Gtk.ResponseOk -> return (UsrEv (OkCancel True))+ Gtk.ResponseCancel -> return (UsrEv (OkCancel False))+ Gtk.ResponseUser 1 -> return (UsrEv ChangeDialog) _ -> return (UsrEv (OkCancel False)) minibufInit :: MainCoroutine (Either () [Stroke])@@ -135,14 +149,18 @@ minibufStart drawwdw (srcsfc,tgtsfc) empty _ -> minibufInit) -invalidateMinibuf :: DrawWindow -> Cairo.Surface -> IO ()+invalidateMinibuf :: Gtk.DrawWindow -> Cairo.Surface -> IO () invalidateMinibuf drawwdw tgtsfc = - renderWithDrawable drawwdw $ do +#ifdef GTK3+ Gtk.renderWithDrawWindow drawwdw $ do +#else + Gtk.renderWithDrawable drawwdw $ do +#endif Cairo.setSourceSurface tgtsfc 0 0 Cairo.setOperator Cairo.OperatorSource Cairo.paint -minibufStart :: DrawWindow +minibufStart :: Gtk.DrawWindow -> (Cairo.Surface,Cairo.Surface) -- ^ (source, target) -> Seq Stroke -> MainCoroutine (Either () [Stroke])@@ -161,7 +179,7 @@ minibufStart drawwdw (srcsfc,tgtsfc) nstrks _ -> minibufStart drawwdw (srcsfc,tgtsfc) strks -onestroke :: DrawWindow+onestroke :: Gtk.DrawWindow -> (Cairo.Surface,Cairo.Surface) -- ^ (source, target) -> Seq PointerCoord -> MainCoroutine (Seq PointerCoord)
src/Hoodle/Coroutine/Mode.hs view
@@ -5,7 +5,7 @@ -- Module : Hoodle.Coroutine.Mode -- Copyright : (c) 2011-2014 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -15,10 +15,10 @@ module Hoodle.Coroutine.Mode where import Control.Applicative-import Control.Lens (view,set,over)+import Control.Lens (view,set,(.~)) import Control.Monad.State import qualified Data.IntMap as M-import Graphics.UI.Gtk (adjustmentGetValue) +import qualified Graphics.UI.Gtk as Gtk (adjustmentGetValue) -- from hoodle-platform import Data.Hoodle.BBox import Data.Hoodle.Generic@@ -45,107 +45,109 @@ modeChange command = do case command of ToViewAppendMode -> updateXState select2edit >> invalidateAll - -- invalidateAllInBBox Nothing Efficient -- invalidateAll - ToSelectMode -> updateXState edit2select >> invalidateAllInBBox Nothing Efficient -- invalidateAll + ToSelectMode -> updateXState edit2select >> invalidateAllInBBox Nothing Efficient _ -> return () reflectPenModeUI reflectPenColorUI reflectPenWidthUI where select2edit xst = - either (noaction xst) (whenselect xst) . hoodleModeStateEither . view hoodleModeState $ xst+ either (noaction xst) (whenselect xst) . hoodleModeStateEither + . view (unitHoodles.currentUnit.hoodleModeState) $ xst edit2select xst = - either (whenedit xst) (noaction xst) . hoodleModeStateEither . view hoodleModeState $ xst+ either (whenedit xst) (noaction xst) . hoodleModeStateEither + . view (unitHoodles.currentUnit.hoodleModeState) $ xst noaction :: HoodleState -> a -> MainCoroutine HoodleState- noaction xstate = const (return xstate)+ noaction xst = const (return xst) whenselect :: HoodleState -> Hoodle SelectMode -> MainCoroutine HoodleState- whenselect xstate thdl = do + whenselect xst thdl = do let pages = view gselAll thdl mselect = view gselSelected thdl- cache = view renderCache xstate+ cid = getCurrentCanvasId (view (unitHoodles.currentUnit) xst) npages <- maybe (return pages) (\(spgn,spage) -> do - npage <- (liftIO.updatePageBuf cache.hPage2RPage) spage + let npage = hPage2RPage spage+ callRenderer_ $ updatePageBuf cid npage return $ M.adjust (const npage) spgn pages ) mselect let nthdl = set gselAll npages . set gselSelected Nothing $ thdl - return . flip (set hoodleModeState) xstate - . ViewAppendState . gSelect2GHoodle $ nthdl + return $ (unitHoodles.currentUnit.hoodleModeState .~ ViewAppendState (gSelect2GHoodle nthdl)) xst whenedit :: HoodleState -> Hoodle EditMode -> MainCoroutine HoodleState - whenedit xstate hdl = do - return . flip (set hoodleModeState) xstate - . SelectState - . gHoodle2GSelect $ hdl + whenedit xst hdl =+ return $ (unitHoodles.currentUnit.hoodleModeState .~ SelectState (gHoodle2GSelect hdl)) xst + -- | viewModeChange :: UserEvent -> MainCoroutine () viewModeChange command = do case command of - ToSinglePage -> updateXState cont2single >> invalidateAll - ToContSinglePage -> updateXState single2cont >> invalidateAll + ToSinglePage -> updateUhdl cont2single >> invalidateAll + ToContSinglePage -> updateUhdl single2cont >> invalidateAll _ -> return () adjustScrollbarWithGeometryCurrent - where cont2single xst = - unboxBiAct (noaction xst) (whencont xst) . view currentCanvasInfo $ xst- single2cont xst = - unboxBiAct (whensing xst) (noaction xst) . view currentCanvasInfo $ xst- noaction :: HoodleState -> a -> MainCoroutine HoodleState - noaction xstate = const (return xstate)- -------------------------------------- whencont xstate cinfo = do - geometry <- liftIO $ getGeometry4CurrCvs xstate - cdim <- liftIO $ return . canvasDim $ geometry - page <- getCurrentPageCurr- let zmode = view (viewInfo.zoomMode) cinfo- canvas = view drawArea cinfo - cpn = PageNum . view currentPageNum $ cinfo + where cont2single :: UnitHoodle -> MainCoroutine UnitHoodle+ cont2single uhdl = unboxBiAct (const (return uhdl)) (cont2SingPage uhdl) . view currentCanvasInfo $ uhdl+ single2cont :: UnitHoodle -> MainCoroutine UnitHoodle+ single2cont uhdl = unboxBiAct (sing2ContPage uhdl) (const (return uhdl)) . view currentCanvasInfo $ uhdl - pdim = PageDimension (view gdimension page)- ViewPortBBox bbox = view (viewInfo.pageArrangement.viewPortBBox) cinfo - (x0,y0) = bbox_upperleft bbox - (xpos,ypos) = maybe (0,0) (unPageCoord.snd) $ desktop2Page geometry (DeskCoord (x0,y0)) - let arr = makeSingleArrangement zmode pdim cdim (xpos,ypos) - let nvinfo = ViewInfo (view zoomMode (view viewInfo cinfo)) arr - ncinfo = CanvasInfo (view canvasId cinfo)- canvas- (view mDrawSurface cinfo)- (view scrolledWindow cinfo)- nvinfo - (unPageNum cpn)- (view horizAdjustment cinfo)- (view vertAdjustment cinfo)- (view horizAdjConnId cinfo)- (view vertAdjConnId cinfo)- (view canvasWidgets cinfo)- (view notifiedItem cinfo)- return $ set currentCanvasInfo (CanvasSinglePage ncinfo) xstate - -------------------------------------- whensing xstate cinfo = do - cdim <- liftIO $ return . canvasDim =<< getGeometry4CurrCvs xstate - let zmode = view (viewInfo.zoomMode) cinfo- canvas = view drawArea cinfo - cpn = PageNum . view currentPageNum $ cinfo - (hadj,vadj) = view adjustments cinfo - (xpos,ypos) <- liftIO $ (,) <$> adjustmentGetValue hadj <*> adjustmentGetValue vadj- let arr = makeContinuousArrangement zmode cdim (getHoodle xstate) - (cpn, PageCoord (xpos,ypos))- geometry <- liftIO $ makeCanvasGeometry cpn arr canvas- let DeskCoord (nxpos,nypos) = page2Desktop geometry (cpn,PageCoord (xpos,ypos))- let vinfo = view viewInfo cinfo - nvinfo = ViewInfo (view zoomMode vinfo) arr - ncinfotemp = CanvasInfo (view canvasId cinfo)- (view drawArea cinfo)- (view mDrawSurface cinfo)- (view scrolledWindow cinfo)- nvinfo - (view currentPageNum cinfo)- hadj - vadj - (view horizAdjConnId cinfo)- (view vertAdjConnId cinfo)- (view canvasWidgets cinfo) - (view notifiedItem cinfo)- ncpn = maybe cpn fst $ desktop2Page geometry (DeskCoord (nxpos,nypos))- ncinfo = over currentPageNum (const (unPageNum ncpn)) ncinfotemp- return . over currentCanvasInfo (const (CanvasContPage ncinfo)) $ xstate+cont2SingPage :: UnitHoodle -> CanvasInfo a -> MainCoroutine UnitHoodle+cont2SingPage uhdl cinfo = do+ geometry <- liftIO $ getGeometry4CurrCvs uhdl+ cdim <- liftIO $ return . canvasDim $ geometry + page <- getCurrentPageCurr+ let zmode = view (viewInfo.zoomMode) cinfo+ canvas = view drawArea cinfo + cpn = PageNum . view currentPageNum $ cinfo ++ pdim = PageDimension (view gdimension page)+ ViewPortBBox bbox = view (viewInfo.pageArrangement.viewPortBBox) cinfo + (x0,y0) = bbox_upperleft bbox + (xpos,ypos) = maybe (0,0) (unPageCoord.snd) $ desktop2Page geometry (DeskCoord (x0,y0)) + let arr = makeSingleArrangement zmode pdim cdim (xpos,ypos) + let nvinfo = ViewInfo (view zoomMode (view viewInfo cinfo)) arr + ncinfo = CanvasInfo (view canvasId cinfo)+ canvas+ (view mDrawSurface cinfo)+ (view scrolledWindow cinfo)+ nvinfo + (unPageNum cpn)+ (view horizAdjustment cinfo)+ (view vertAdjustment cinfo)+ (view horizAdjConnId cinfo)+ (view vertAdjConnId cinfo)+ (view canvasWidgets cinfo)+ (view notifiedItem cinfo)+ return $ (currentCanvasInfo .~ CanvasSinglePage ncinfo) uhdl+++sing2ContPage :: UnitHoodle -> CanvasInfo a -> MainCoroutine UnitHoodle+sing2ContPage uhdl cinfo = do+ cdim <- liftIO $ return . canvasDim =<< getGeometry4CurrCvs uhdl+ let zmode = view (viewInfo.zoomMode) cinfo+ canvas = view drawArea cinfo + cpn = PageNum . view currentPageNum $ cinfo + (hadj,vadj) = view adjustments cinfo + (xpos,ypos) <- liftIO $ (,) <$> Gtk.adjustmentGetValue hadj <*> Gtk.adjustmentGetValue vadj+ let arr = makeContinuousArrangement zmode cdim (getHoodle uhdl) + (cpn, PageCoord (xpos,ypos))+ geometry <- liftIO $ makeCanvasGeometry cpn arr canvas+ let DeskCoord (nxpos,nypos) = page2Desktop geometry (cpn,PageCoord (xpos,ypos))+ let vinfo = view viewInfo cinfo + nvinfo = ViewInfo (view zoomMode vinfo) arr + ncinfotemp = CanvasInfo (view canvasId cinfo)+ (view drawArea cinfo)+ (view mDrawSurface cinfo)+ (view scrolledWindow cinfo)+ nvinfo + (view currentPageNum cinfo)+ hadj + vadj + (view horizAdjConnId cinfo)+ (view vertAdjConnId cinfo)+ (view canvasWidgets cinfo) + (view notifiedItem cinfo)+ ncpn = maybe cpn fst $ desktop2Page geometry (DeskCoord (nxpos,nypos))+ ncinfo = (currentPageNum .~ unPageNum ncpn) ncinfotemp+ return $ (currentCanvasInfo .~ CanvasContPage ncinfo) uhdl+
src/Hoodle/Coroutine/Network.hs view
@@ -7,7 +7,7 @@ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Coroutine.Network--- Copyright : (c) 2013 Ian-Woo Kim+-- Copyright : (c) 2013, 2014 Ian-Woo Kim -- -- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>@@ -20,86 +20,83 @@ import Control.Applicative import Control.Concurrent hiding (yield)- import Control.Lens --import Control.Monad.State (modify,get)+import Control.Monad+import Control.Monad.Loops +import Control.Monad.State (get) import Control.Monad.Trans import Control.Monad.Trans.Maybe (MaybeT(..)) import qualified Data.Binary as Bi import qualified Data.ByteString.Char8 as B import qualified Data.ByteString.Lazy.Char8 as LB-import qualified Data.Foldable as F (mapM_)-+-- import qualified Data.Foldable as F (mapM_)+import Data.IORef import Data.Monoid ((<>),mconcat) import qualified Data.Text as T import qualified Data.Text.Encoding as TE+import qualified Data.Traversable as Tr import Data.Word-import Graphics.UI.Gtk hiding (get,set)+import qualified Graphics.UI.Gtk as Gtk import Network.Info import Network.Simple.TCP- -- --import Control.Monad.Trans.Crtn.Queue (enqueue)--- - import Hoodle.Coroutine.Draw import Hoodle.Script.Hook import Hoodle.Type.Coroutine import Hoodle.Type.Enum import Hoodle.Type.Event-import Hoodle.Type.HoodleState (tempQueue,hookSet)+import Hoodle.Type.HoodleState (hookSet) -- server :: (AllEvent -> IO ()) -> HostPreference -> T.Text -> IO ()-server evhandler ip txt = do- listen ip "4040" $ \(lsock, _) -> - accept lsock $ \(sock,addr) -> do - let bstr = TE.encodeUtf8 txt- bstr_size :: Word32 = (fromIntegral . B.length) bstr - bstr_size_binary = (mconcat . LB.toChunks . Bi.encode) bstr_size- -- B.putStrLn () - putStrLn $ "TCP connection established from " ++ show addr- send sock (bstr_size_binary <> TE.encodeUtf8 txt)- - mbstr <- runMaybeT $ do - bstr' <- MaybeT (recv sock 4)- let getsize :: B.ByteString -> Word32 - getsize = Bi.decode . LB.fromChunks . return- size = (fromIntegral . getsize) bstr'+server evhandler ip txtorig = do+ ref <- newIORef txtorig+ forever $ listen ip "4040" $ \(lsock, _) -> + accept lsock $ \(sock,addr) -> do+ txt <- readIORef ref+ let bstr = TE.encodeUtf8 txt+ bstr_size :: Word32 = (fromIntegral . B.length) bstr + bstr_size_binary = (mconcat . LB.toChunks . Bi.encode) bstr_size+ putStrLn $ "TCP connection established from " ++ show addr+ send sock (bstr_size_binary <> TE.encodeUtf8 txt)+ unfoldM_ $ do+ mbstr <- runMaybeT $ do + bstr' <- MaybeT (recv sock 4)+ let getsize :: B.ByteString -> Word32 + getsize = Bi.decode . LB.fromChunks . return+ size = (fromIntegral . getsize) bstr' - go s bs = do - liftIO $ putStrLn ("requested size = " ++ show s)- bstr1 <- MaybeT (recv sock s)- let s' = B.length bstr1 - liftIO $ putStrLn ("obtained size = " ++ show s')- if s <= s' - then return (bs <> bstr1)- else go (s-s') (bs <> bstr1) - go size B.empty - - -- print mbstr - F.mapM_ (evhandler . UsrEv . NetworkProcess . NetworkReceived . TE.decodeUtf8) mbstr+ go s bs = do + liftIO $ putStrLn ("requested size = " ++ show s)+ bstr1 <- MaybeT (recv sock s)+ let s' = B.length bstr1 + liftIO $ putStrLn ("obtained size = " ++ show s')+ if s <= s' + then return (bs <> bstr1)+ else go (s-s') (bs <> bstr1) + go size B.empty + Tr.forM mbstr $ \bstr' -> do + let txt' = TE.decodeUtf8 bstr'+ (evhandler . UsrEv . NetworkProcess . NetworkReceived) txt'+ writeIORef ref txt'+ return mbstr+ putStrLn "FINISHED" -networkTextInput :: T.Text -> MainCoroutine (Maybe T.Text)-networkTextInput txt = do ++networkTextInputBody :: T.Text -> MainCoroutine (String,ThreadId,MVar ()) -- ^ (ip address,thread id,lock)+networkTextInputBody txt = do mipscr <- runMaybeT $ do hkset <- MaybeT (view hookSet <$> lift get) (MaybeT . return) (getIPaddress hkset) - let ipfind = do let ipv4num (IPv4 x) = x ismacnull (MAC a b c d e f) = a == 0 && b == 0 && c == 0 && d == 0 && e == 0 && f == 0 - ifcs <- liftIO $ getNetworkInterfaces let ifcs2 = Prelude.filter (not . ismacnull . mac) . Prelude.filter (((/=) 0) . ipv4num . ipv4 ) $ ifcs return (if Prelude.null ifcs2 then "127.0.0.1" else (show . ipv4 . head) ifcs2) ip <- maybe ipfind liftIO mipscr - doIOaction $ \evhandler -> do - -- T.putStrLn txt done <- newEmptyMVar tid <- forkIO (server evhandler (Host ip) txt) (return . UsrEv . NetworkProcess) (NetworkInitialized tid done)@@ -110,23 +107,24 @@ NetworkProcess (NetworkInitialized tid done) -> return (tid,done) _ -> go (tid,done) <- go - let ipdialog msg = mkIOaction $ - \_evhandler -> do - dialog <- messageDialogNew Nothing [DialogModal]- MessageQuestion ButtonsOkCancel msg - forkIO $ do - readMVar done - dialogResponse dialog ResponseOk- - res <- dialogRun dialog - let b = case res of - ResponseOk -> True- _ -> False- widgetDestroy dialog - return (UsrEv (OkCancel b))+ return (ip,tid,done) - - modify (tempQueue %~ enqueue (ipdialog ("networkedit " ++ ip ++ " 4040")))+networkTextInput :: T.Text -> MainCoroutine (Maybe T.Text)+networkTextInput txt = do + (ip,tid,done) <- networkTextInputBody txt+ let ipdialog msg = \_evhandler -> do + dialog <- Gtk.messageDialogNew Nothing [Gtk.DialogModal]+ Gtk.MessageQuestion Gtk.ButtonsOkCancel msg + forkIO $ do + readMVar done + Gtk.dialogResponse dialog Gtk.ResponseOk+ res <- Gtk.dialogRun dialog + let b = case res of + Gtk.ResponseOk -> True+ _ -> False+ Gtk.widgetDestroy dialog + return (UsrEv (OkCancel b))+ doIOaction (ipdialog ("networkedit " ++ ip ++ " 4040")) -- let actf t = do r <- nextevent@@ -136,7 +134,7 @@ OkCancel True -> (return . Just) t OkCancel False -> return Nothing NetworkProcess (NetworkReceived txt') -> do - doIOaction $ \_ -> postGUISync (putMVar done ())+ doIOaction $ \_ -> Gtk.postGUISync (putMVar done ()) >> (return . UsrEv . NetworkProcess) NetworkCloseDialog actf txt' @@ -148,4 +146,5 @@ (return . UsrEv . NetworkProcess) NetworkClosed -- return ntxt+
src/Hoodle/Coroutine/Page.hs view
@@ -7,9 +7,9 @@ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Coroutine.Page --- Copyright : (c) 2011-2014 Ian-Woo Kim+-- Copyright : (c) 2011-2015 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -19,9 +19,8 @@ module Hoodle.Coroutine.Page where import Control.Applicative-import Control.Concurrent import Control.Concurrent.STM-import Control.Lens (view,set,over, (.~), (^.) )+import Control.Lens (view,set,(.~), (^.)) import Control.Monad import Control.Monad.State import Control.Monad.Trans.Reader (ask)@@ -29,17 +28,11 @@ import Data.Function (on) import qualified Data.IntMap as M import Data.List (sortBy)-import Data.UUID.V4-import qualified Graphics.Rendering.Cairo as Cairo-import qualified Graphics.UI.Gtk as Gtk-import qualified Graphics.UI.Gtk.Poppler.Page as PopplerPage -- from hoodle-platform import Data.Hoodle.Generic import Data.Hoodle.Select import Data.Hoodle.Simple (Dimension(..)) import Data.Hoodle.Zipper-import Graphics.Hoodle.Render--- import Graphics.Hoodle.Render.Background import Graphics.Hoodle.Render.Type -- from this package import Hoodle.Accessor@@ -50,7 +43,6 @@ import Hoodle.Type.Alias import Hoodle.Type.Coroutine import Hoodle.Type.Canvas-import Hoodle.Type.Event import Hoodle.Type.PageArrangement import Hoodle.Type.HoodleState import Hoodle.Type.Enum@@ -60,35 +52,33 @@ -- | change page of current canvas using a modify function changePage :: (Int -> Int) -> MainCoroutine () -changePage modifyfn = updateXState changePageAction - >> adjustScrollbarWithGeometryCurrent- >> invalidateAllInBBox Nothing Efficient - where changePageAction xst = unboxBiAct (fsingle xst) (fcont xst) - . (^. currentCanvasInfo) $ xst- fsingle xstate cvsInfo = do - let xojst = view hoodleModeState $ xstate +changePage modifyfn = (view backgroundStyle <$> get) >>= \bsty -> + updateUhdl (changePageAction bsty) >>+ adjustScrollbarWithGeometryCurrent >>+ invalidateAllInBBox Nothing Efficient + where changePageAction bsty uhdl = unboxBiAct (fsingle bsty uhdl) (fcont bsty uhdl) + . (^. currentCanvasInfo) $ uhdl+ fsingle bsty uhdl cvsInfo = do + let xojst = view hoodleModeState $ uhdl npgnum = modifyfn (cvsInfo ^. currentPageNum) cid = view canvasId cvsInfo- bsty = view backgroundStyle xstate (b,npgnum',_,xojst') <- changePageInHoodleModeState bsty npgnum xojst- xstate' <- liftIO $ updatePageAll xojst' xstate - ncvsInfo <- liftIO $ setPage xstate' (PageNum npgnum') cid- let xstatefinal = (currentCanvasInfo .~ ncvsInfo) xstate'- when b (commit xstatefinal)- return xstatefinal + uhdl' <- liftIO $ updatePageAll xojst' uhdl+ ncvsInfo <- liftIO $ setPage uhdl' (PageNum npgnum') cid+ let uhdlfinal = (currentCanvasInfo .~ ncvsInfo) uhdl'+ when b $ updateUhdl (const (return uhdlfinal)) >> commit_+ return uhdlfinal - fcont xstate cvsInfo = do - let xojst = view hoodleModeState xstate + fcont bsty uhdl cvsInfo = do + let xojst = view hoodleModeState uhdl npgnum = modifyfn (cvsInfo ^. currentPageNum) cid = cvsInfo ^. canvasId- bsty = xstate ^. backgroundStyle- (b,npgnum',_selectedpage,xojst')- <- changePageInHoodleModeState bsty npgnum xojst- xstate' <- liftIO $ updatePageAll xojst' xstate - ncvsInfo <- liftIO $ setPage xstate' (PageNum npgnum') cid- xstatefinal <- return . over currentCanvasInfo (const ncvsInfo) $ xstate'- when b (commit xstatefinal)- return xstatefinal + (b,npgnum',_,xojst') <- changePageInHoodleModeState bsty npgnum xojst+ uhdl' <- liftIO $ updatePageAll xojst' uhdl+ ncvsInfo <- liftIO $ setPage uhdl' (PageNum npgnum') cid+ let uhdlfinal = (currentCanvasInfo .~ ncvsInfo) uhdl'+ when b $ updateUhdl (const (return uhdlfinal)) >> commit_+ return uhdlfinal -- | @@ -97,7 +87,7 @@ -> HoodleModeState -> MainCoroutine (Bool,Int,Page EditMode,HoodleModeState) changePageInHoodleModeState bsty npgnum hdlmodst = do- let ehdl = hoodleModeStateEither hdlmodst + let ehdl = hoodleModeStateEither hdlmodst pgs = either (view gpages) (view gselAll) ehdl totnumpages = M.size pgs lpage = maybeError' "changePage" (M.lookup (totnumpages-1) pgs)@@ -107,9 +97,8 @@ let cbkg = view gbackground lpage nbkg <- newBkg bsty cbkg npage <- set gbackground nbkg <$> (newPageFromOld lpage)- geometry <- liftIO . getGeometry4CurrCvs =<< get- callRenderer $ updateBkgCache geometry (PageNum (totnumpages-1),npage) >> return GotNone- waitSomeEvent (\case RenderEv GotNone -> True ; _ -> False )+ geometry <- liftIO . getGeometry4CurrCvs . view (unitHoodles.currentUnit) =<< get+ callRenderer_ $ updatePageCache geometry (PageNum (totnumpages-1),npage) let npages = M.insert totnumpages npage pgs return (True,totnumpages,npage, either (Left . set gpages npages) (Right. set gselAll npages) ehdl ) @@ -127,18 +116,19 @@ -> Maybe (PageNum,PageCoordinate) -> MainCoroutine () canvasZoomUpdateGenRenderCvsId renderfunc cid mzmode mcoord = do - updateXState zoomUpdateAction + updateUhdl zoomUpdateAction adjustScrollbarWithGeometryCvsId cid xst <- get- let hdl = getHoodle xst- geometry <- liftIO (getGeometry4CurrCvs xst)- let cpn = view (unboxLens currentPageNum) . getCanvasInfo cid $ xst+ let uhdl = view (unitHoodles.currentUnit) xst+ hdl = getHoodle uhdl+ geometry <- liftIO (getGeometry4CurrCvs uhdl)+ let cpn = view (unboxLens currentPageNum) . getCanvasInfo cid $ uhdl let plst = sortBy ( compare `on` (\(n,_) -> abs (n - cpn)) ) . zip [0..] . F.toList $ hdl ^. gpages- forM_ plst $ \(pn,pg) -> callRenderer_ (updateBkgCache geometry (PageNum pn,pg))+ forM_ plst $ \(pn,pg) -> callRenderer_ (updatePageCache geometry (PageNum pn,pg)) renderfunc- where zoomUpdateAction xst = - unboxBiAct (fsingle xst) (fcont xst) . getCanvasInfo cid $ xst - fsingle xstate cinfo = do + where zoomUpdateAction uhdl = + unboxBiAct (fsingle uhdl) (fcont uhdl) . getCanvasInfo cid $ uhdl + fsingle uhdl cinfo = do geometry <- liftIO $ getCvsGeomFrmCvsInfo cinfo page <- getCurrentPageCvsId cid let zmode = maybe (cinfo ^. viewInfo.zoomMode) id mzmode @@ -150,13 +140,13 @@ ncinfobox = CanvasSinglePage . (viewInfo.pageArrangement .~ narr) . (viewInfo.zoomMode .~ zmode) $ cinfo- return . modifyCanvasInfo cid (const ncinfobox) $ xstate- fcont xstate cinfo = do + return . modifyCanvasInfo cid (const ncinfobox) $ uhdl+ fcont uhdl cinfo = do geometry <- liftIO $ getCvsGeomFrmCvsInfo cinfo let zmode = maybe (view (viewInfo.zoomMode) cinfo) id mzmode cpn = PageNum $ view currentPageNum cinfo cdim = canvasDim geometry - hdl = getHoodle xstate + hdl = getHoodle uhdl origcoord = case mcoord of Just coord -> coord Nothing -> either (const (cpn,PageCoord (0,0))) id @@ -165,7 +155,7 @@ ncinfobox = CanvasContPage . (viewInfo.pageArrangement .~ narr) . (viewInfo.zoomMode .~ zmode) $ cinfo- return . modifyCanvasInfo cid (const ncinfobox) $ xstate+ return . modifyCanvasInfo cid (const ncinfobox) $ uhdl -- | canvasZoomUpdateCvsId :: CanvasId @@ -177,7 +167,7 @@ -- | canvasZoomUpdateBufAll :: MainCoroutine () canvasZoomUpdateBufAll = do - klst <- liftM (M.keys . getCanvasInfoMap) get+ klst <- M.keys . view cvsInfoMap . view (unitHoodles.currentUnit) <$> get mapM_ updatefunc klst where updatefunc cid @@ -187,14 +177,14 @@ -- | canvasZoomUpdateAll :: MainCoroutine () canvasZoomUpdateAll = do - klst <- liftM (M.keys . getCanvasInfoMap) get+ klst <- M.keys . view cvsInfoMap . view (unitHoodles.currentUnit) <$> get mapM_ (flip canvasZoomUpdateCvsId Nothing) klst -- | canvasZoomUpdate :: Maybe ZoomMode -> MainCoroutine () canvasZoomUpdate mzmode = do - cid <- (liftM (getCurrentCanvasId) get)+ cid <- getCurrentCanvasId . view (unitHoodles.currentUnit) <$> get canvasZoomUpdateCvsId cid mzmode -- |@@ -204,7 +194,7 @@ -- | pageZoomChangeRel :: ZoomModeRel -> MainCoroutine () pageZoomChangeRel rzmode = do - forBoth' unboxBiAct fsingle . view currentCanvasInfo =<< get + forBoth' unboxBiAct fsingle . view currentCanvasInfo . view (unitHoodles.currentUnit) =<< get where fsingle :: CanvasInfo a -> MainCoroutine () fsingle cinfo = do @@ -216,42 +206,45 @@ pageZoomChange (Zoom nratio) -- |-newPage :: AddDirection -> MainCoroutine () -newPage dir = updateXState npgBfrAct - >> commit_ - >> canvasZoomUpdateAll - >> invalidateAll+newPage :: Maybe Dimension -> AddDirection -> MainCoroutine () +newPage mdim dir = (view backgroundStyle <$> get) >>= \bsty ->+ updateUhdl (npgBfrAct bsty) >>+ commit_ >>+ canvasZoomUpdateAll >>+ invalidateAll where - npgBfrAct xst = forBoth' unboxBiAct (fsimple xst) . view currentCanvasInfo $ xst- fsimple :: HoodleState -> CanvasInfo a -> MainCoroutine HoodleState- fsimple xstate cinfo = do - case view hoodleModeState xstate of + npgBfrAct bsty uhdl = forBoth' unboxBiAct (fsimple bsty uhdl) . view currentCanvasInfo $ uhdl+ fsimple :: BackgroundStyle -> UnitHoodle -> CanvasInfo a -> MainCoroutine UnitHoodle+ fsimple bsty uhdl cinfo = do + case view hoodleModeState uhdl of ViewAppendState hdl -> do - let bsty = view backgroundStyle xstate - hdl' <- addNewPageInHoodle bsty dir hdl (view currentPageNum cinfo)- return =<< liftIO . updatePageAll (ViewAppendState hdl')- . set hoodleModeState (ViewAppendState hdl') $ xstate + hdl' <- addNewPageInHoodle mdim bsty dir hdl (view currentPageNum cinfo)+ liftIO . updatePageAll (ViewAppendState hdl')+ . set hoodleModeState (ViewAppendState hdl') $ uhdl SelectState _ -> do - liftIO $ putStrLn " not implemented yet"- return xstate+ msgShout "newPage: not implemented yet"+ return uhdl -- | delete current page of current canvas deleteCurrentPage :: MainCoroutine () -deleteCurrentPage = do - updateXState delpgact >> commit_ >> canvasZoomUpdateAll >> invalidateAll+deleteCurrentPage = + updateUhdl delpgact >> + commit_ >> + canvasZoomUpdateAll >> + invalidateAll where - delpgact xst = forBoth' unboxBiAct (fsimple xst) . view currentCanvasInfo $ xst- fsimple :: HoodleState -> CanvasInfo a -> MainCoroutine HoodleState- fsimple xstate cinfo = do - case view hoodleModeState xstate of + delpgact uhdl = forBoth' unboxBiAct (fsimple uhdl) . view currentCanvasInfo $ uhdl+ fsimple :: UnitHoodle -> CanvasInfo a -> MainCoroutine UnitHoodle+ fsimple uhdl cinfo = do + case view hoodleModeState uhdl of ViewAppendState hdl -> do hdl' <- liftIO $ deletePageInHoodle hdl (PageNum (view currentPageNum cinfo))- return =<< liftIO . updatePageAll (ViewAppendState hdl')- . set hoodleModeState (ViewAppendState hdl') $ xstate + liftIO . updatePageAll (ViewAppendState hdl')+ . set hoodleModeState (ViewAppendState hdl') $ uhdl SelectState _ -> do - liftIO $ putStrLn " not implemented yet"- return xstate+ msgShout "deleteCurrentPage: not implemented yet"+ return uhdl -- | delete designated page deletePageInHoodle :: Hoodle EditMode -> PageNum -> IO (Hoodle EditMode)@@ -264,19 +257,20 @@ -- | -addNewPageInHoodle :: BackgroundStyle+addNewPageInHoodle :: Maybe Dimension+ -> BackgroundStyle -> AddDirection -> Hoodle EditMode -> Int -> MainCoroutine (Hoodle EditMode)-addNewPageInHoodle bsty dir hdl cpn = do+addNewPageInHoodle mdim bsty dir hdl cpn = do let pagelst = M.elems . view gpages $ hdl (pagesbefore,cpage:pagesafter) = splitAt cpn pagelst cbkg = view gbackground cpage nbkg <- newBkg bsty cbkg- npage <- set gbackground nbkg <$> newPageFromOld cpage- geometry <- liftIO . getGeometry4CurrCvs =<< get- callRenderer_ (updateBkgCache geometry (PageNum cpn,npage))+ npage <- maybe id (set gdimension) mdim . set gbackground nbkg <$> newPageFromOld cpage+ geometry <- liftIO . getGeometry4CurrCvs . view (unitHoodles.currentUnit) =<< get+ callRenderer_ (updatePageCache geometry (PageNum cpn,npage)) let npagelst = case dir of PageBefore -> pagesbefore ++ (npage : cpage : pagesafter) PageAfter -> pagesbefore ++ (cpage : npage : pagesafter)@@ -286,40 +280,85 @@ newBkg :: BackgroundStyle -> RBackground -> MainCoroutine RBackground newBkg bsty bkg = do+ xst <- get+ let npmode = xst ^. settings.newPageMode+ rhdl = (getHoodle . view (unitHoodles.currentUnit)) xst+ mtotN = pdfNumPages <$> (rhdl ^. gembeddedpdf) let bstystr = convertBackgroundStyleToByteString bsty - case bkg of - RBkgSmpl c _ _ -> RBkgSmpl c bstystr <$> liftIO nextRandom- _ -> RBkgSmpl "white" bstystr <$> liftIO nextRandom+ defbkg = RBkgSmpl "white" bstystr <$> issueSurfaceID+ case npmode of + NPPlain -> defbkg+ NPLast -> case bkg of + RBkgSmpl c _ _ -> RBkgSmpl c bstystr <$> issueSurfaceID+ RBkgPDF d f n pg _ -> RBkgPDF d f n pg <$> issueSurfaceID+ RBkgEmbedPDF n pg _ -> RBkgEmbedPDF n pg <$> issueSurfaceID+ NPCycle -> + case mtotN of+ Nothing -> defbkg+ Just totN -> do+ let n1 = maybe 1 id (xst ^. nextPdfBkgPageNum)+ case findPDFBkg rhdl n1 of+ Nothing -> defbkg+ Just bkg' -> issueSurfaceID >>= \i -> do+ let n' = if n1 >= totN then 1 else (n1+1)+ put ((nextPdfBkgPageNum .~ Just n') xst)+ return bkg' { rbkg_surfaceid = i } +findPDFBkg :: RHoodle -> Int -> Maybe RBackground+findPDFBkg rhdl n1 = + let bkgs = M.elems (rhdl ^. gpages)+ pagematch n (RBkgPDF _ _ n' _ _) = n == n'+ pagematch n (RBkgEmbedPDF n' _ _) = n == n'+ pagematch _ _ = False+ matched = (filter (pagematch n1) . map (^. gbackground)) bkgs+ in case matched of + [] -> Nothing+ b:_ -> Just b++ -- | newPageFromOld :: Page EditMode -> MainCoroutine (Page EditMode)-newPageFromOld =- return . ( glayers .~ (fromNonEmptyList (emptyRLayer,[])))+newPageFromOld pg = do+ sfcid <- issueSurfaceID+ return . ( glayers .~ (fromNonEmptyList (emptyRLayer sfcid,[]))) $ pg -updateBkgCache :: CanvasGeometry -> (PageNum, Page EditMode) -> Renderer ()-updateBkgCache geometry (pnum,page) = do- (handler,qvar) <- ask- let dim@(Dim w h) = page ^. gdimension +updatePageCache :: CanvasGeometry -> (PageNum, Page EditMode) -> Renderer ()+updatePageCache geometry (pnum,page) = do+ let Dim w h = page ^. gdimension CvsCoord (x0,y0) = (desktop2Canvas geometry . page2Desktop geometry) (pnum,PageCoord (0,0)) CvsCoord (x1,y1) = (desktop2Canvas geometry . page2Desktop geometry) (pnum,PageCoord (w,h))- s = (x1-x0) / w - rbkg = page ^. gbackground- bkg = rbkg2Bkg rbkg- uuid = rbkg_uuid rbkg + updateBkgCache (Dim w h) (Dim (x1-x0) (y1-y0)) (page ^. gbackground) + mapM_ (updateLayerCache (Dim w h) (Dim (x1-x0) (y1-y0))) (F.toList (page ^. glayers))+++updateBkgCache :: Dimension -> Dimension -> RBackground -> Renderer ()+updateBkgCache dimo dimv rbkg = do+ RendererState _handler qpdf qgen _ <- ask+ let sfcid = rbkg_surfaceid rbkg case rbkg of - RBkgSmpl {..} -> do liftIO . forkIO $ do- sfc <- Cairo.createImageSurface Cairo.FormatARGB32 (floor (x1-x0)) (floor (y1-y0))- Cairo.renderWith sfc $ Cairo.scale s s >> renderBkg (bkg,dim)- handler (uuid, (s,sfc))- return ()- + RBkgSmpl {..} -> do+ cmdid <- issueGenCommandID+ (liftIO . atomically) (sendGenCommand qgen cmdid (BkgSmplScaled sfcid rbkg_color rbkg_style dimo dimv))+ return () _ -> F.forM_ (rbkg_popplerpage rbkg) $ \pg -> do- (liftIO . atomically) (sendPDFCommand uuid qvar (RenderPageScaled pg (Dim w h) (Dim (x1-x0) (y1-y0))))- return ()+ cmdid <- issuePDFCommandID+ (liftIO . atomically) (sendPDFCommand qpdf cmdid (RenderPageScaled sfcid pg dimo dimv))+ return ()+++updateLayerCache :: Dimension -> Dimension -> RLayer -> Renderer ()+updateLayerCache dimo dimv lyr = do+ RendererState _ _ qgen _ <- ask+ case view gbuffer lyr of+ LyBuf sfcid -> do+ cmdid <- issueGenCommandID+ (liftIO . atomically) (sendGenCommand qgen cmdid (LayerScaled sfcid (view gitems lyr) dimo dimv))+ return ()+
src/Hoodle/Coroutine/Pen.hs view
@@ -1,11 +1,15 @@-{-# LANGUAGE Rank2Types, GADTs, ScopedTypeVariables, TupleSections #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections #-} ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Coroutine.Pen --- Copyright : (c) 2011-2014 Ian-Woo Kim+-- Copyright : (c) 2011-2015 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -16,27 +20,31 @@ -- from other packages import Control.Applicative ((<$>),(<*>))-import Control.Lens (view,set,at)+import Control.Lens (at,over,set,view) import Control.Monad hiding (mapM_,forM_) import Control.Monad.State hiding (mapM_,forM_) -- import Control.Monad.Trans import Data.Functor.Identity (Identity(..))-import Data.Foldable (forM_)+import Data.Foldable (toList) import Data.Sequence hiding (filter)+import qualified Data.IntMap as IM import Data.Maybe +import Data.Ratio import Data.Time.Clock import qualified Graphics.Rendering.Cairo as Cairo -- from hoodle-platform import Data.Hoodle.BBox-import Data.Hoodle.Generic (gpages)+import Data.Hoodle.Generic (gitems,gpages) import Data.Hoodle.Simple (Dimension(..))-import Graphics.Hoodle.Render (renderStrk)+import Graphics.Hoodle.Render (renderStrk,updateLayerBuf)+import Graphics.Hoodle.Render.Type -- from this package--- import Hoodle.Accessor+import Hoodle.Accessor import Hoodle.Coroutine.Commit import Hoodle.Coroutine.Draw import Hoodle.Device import Hoodle.GUI.Reflect+import Hoodle.ModelAction.Layer import Hoodle.ModelAction.Page import Hoodle.ModelAction.Pen import Hoodle.Type.Canvas@@ -52,17 +60,40 @@ -- import Prelude hiding (mapM_) ++-- | +addPDraw :: CanvasId+ -> PenInfo + -> RHoodle+ -> PageNum + -> Seq (Double,Double,Double) + -> MainCoroutine (RHoodle,BBox) -- ^ new hoodle and bbox in page coordinate+addPDraw cid pinfo hdl (PageNum pgnum) pdraw = do + let currpage = getPageFromGHoodleMap pgnum hdl+ currlayer = getCurrentLayer currpage+ newstroke = createNewStroke pinfo pdraw + newstrokebbox = runIdentity (makeBBoxed newstroke)+ bbox = getBBox newstrokebbox+ newlayerbbox = over gitems (++[RItemStroke newstrokebbox]) currlayer+ callRenderer_ $ updateLayerBuf cid newlayerbbox+ let newpagebbox = adjustCurrentLayer newlayerbbox currpage + newhdlbbox = set gpages (IM.adjust (const newpagebbox) pgnum (view gpages hdl) ) hdl + return (newhdlbbox,bbox)++ -- | createTempRender :: CanvasGeometry -> a -> MainCoroutine (TempRender a) createTempRender geometry x = do xst <- get- let cinfobox = view currentCanvasInfo xst + cache <- renderCache+ let uhdl = view (unitHoodles.currentUnit) xst+ cinfobox = view currentCanvasInfo uhdl mcvssfc = view (unboxLens mDrawSurface) cinfobox - cache = view renderCache xst- let hdl = getHoodle xst- let Dim cw ch = unCanvasDimension . canvasDim $ geometry+ cid = getCurrentCanvasId uhdl+ hdl = getHoodle uhdl+ Dim cw ch = unCanvasDimension . canvasDim $ geometry srcsfc <- liftIO $ - maybe (fst <$> canvasImageSurface cache Nothing geometry hdl)+ maybe (fst <$> canvasImageSurface cache cid Nothing geometry hdl) (\cvssfc -> do sfc <- Cairo.createImageSurface Cairo.FormatARGB32 (floor cw) (floor ch) @@ -83,72 +114,76 @@ penPageSwitch :: PageNum -> MainCoroutine CanvasInfoBox penPageSwitch pgn = do xstate <- get- let cibox = view currentCanvasInfo xstate + let uhdl = view (unitHoodles.currentUnit) xstate+ cibox = view currentCanvasInfo uhdl ncibox = (runIdentity . forBoth unboxBiXform (return . set currentPageNum (unPageNum pgn))) cibox - put (set currentCanvasInfo ncibox xstate) + uhdl' = set currentCanvasInfo ncibox uhdl+ pureUpdateUhdl (const uhdl') invalidateAllInBBox Nothing Efficient return ncibox - -+ -- | Common Pen Work starting point -commonPenStart :: (forall a. CanvasInfo a -> PageNum -> CanvasGeometry - -> (Double,Double) -> MainCoroutine () )+commonPenStart :: forall b. + (forall a . CanvasInfo a -> PageNum -> CanvasGeometry + -> (Double,Double) -> UTCTime -> MainCoroutine b) -> CanvasId -> PointerCoord - -> MainCoroutine ()+ -> MainCoroutine (Maybe b) commonPenStart action cid pcoord = do oxstate <- get - let currcid = getCurrentCanvasId oxstate+ let currcid = (getCurrentCanvasId . view (unitHoodles.currentUnit)) oxstate+ ctime <- liftIO $ getCurrentTime when (cid /= currcid) (changeCurrentCanvasId cid >> invalidateAll) nxstate <- get- forBoth' unboxBiAct f . getCanvasInfo cid $ nxstate- where f :: forall b. CanvasInfo b -> MainCoroutine ()- f cvsInfo = do + forBoth' unboxBiAct (f ctime) . getCanvasInfo cid . view (unitHoodles.currentUnit) $ nxstate+ where f :: forall c. UTCTime -> CanvasInfo c -> MainCoroutine (Maybe b)+ f ctime cvsInfo = do let cpn = PageNum . view currentPageNum $ cvsInfo arr = view (viewInfo.pageArrangement) cvsInfo canvas = view drawArea cvsInfo geometry <- liftIO $ makeCanvasGeometry cpn arr canvas let pagecoord = desktop2Page geometry . device2Desktop geometry $ pcoord - maybeFlip pagecoord (return ()) + maybeFlip pagecoord (return Nothing) $ \(pgn,PageCoord (x,y)) -> do nCvsInfo <- if (cpn /= pgn) then do penPageSwitch pgn -- temporary dirty fix return (set currentPageNum (unPageNum pgn) cvsInfo ) else return cvsInfo - action nCvsInfo pgn geometry (x,y) + Just <$> action nCvsInfo pgn geometry (x,y) ctime -- | enter pen drawing mode penStart :: CanvasId -> PointerCoord - -> MainCoroutine () + -> MainCoroutine (Maybe (Maybe (Maybe ()))) penStart cid pcoord = commonPenStart penAction cid pcoord- where penAction :: forall b. CanvasInfo b -> PageNum -> CanvasGeometry -> (Double,Double) -> MainCoroutine ()- penAction _cinfo pnum geometry (x,y) = do + where penAction :: forall b. CanvasInfo b -> PageNum -> CanvasGeometry + -> (Double,Double) -> UTCTime + -> MainCoroutine (Maybe (Maybe ()))+ penAction _cinfo pnum geometry (x,y) ctime = do xstate <- get+ let uhdl = view (unitHoodles.currentUnit) xstate let PointerCoord _ _ _ z = pcoord - let currhdl = getHoodle xstate + let currhdl = getHoodle uhdl pinfo = view penInfo xstate mpage = view (gpages . at (unPageNum pnum)) currhdl - cache = view renderCache xstate- forM_ mpage $ \_page -> do + maybeFlip mpage (return Nothing) $ \_page -> do trdr <- createTempRender geometry (empty |> (x,y,z)) - pdraw <-penProcess cid pnum geometry trdr ((x,y),z) + mpdraw <-penProcess cid pnum geometry trdr ((x,y),z) ctime Cairo.surfaceFinish (tempSurfaceSrc trdr)- Cairo.surfaceFinish (tempSurfaceTgt trdr) - --- case viewl pdraw of - EmptyL -> return ()- (x1,_y1,_z1) :< _rest -> do - if x1 <= 1e-3 -- this is ad hoc but.. - then invalidateAll- else do - (newhdl,bbox) <- liftIO $ addPDraw cache pinfo currhdl pnum pdraw- commit . set hoodleModeState (ViewAppendState newhdl) - =<< (liftIO (updatePageAll (ViewAppendState newhdl) xstate))- let f = unDeskCoord . page2Desktop geometry . (pnum,) . PageCoord- nbbox = xformBBox f bbox - invalidateAllInBBox (Just nbbox) BkgEfficient + Cairo.surfaceFinish (tempSurfaceTgt trdr)+ maybeFlip mpdraw (return (Just Nothing)) $ \pdraw -> + case viewl pdraw of + EmptyL -> return (Just (Just ()))+ (x1,_y1,_z1) :< _rest -> do + if x1 <= 1e-3 -- this is ad hoc but.. + then invalidateAll+ else do + (newhdl,_bbox) <- addPDraw cid pinfo currhdl pnum pdraw+ uhdl' <- liftIO (updatePageAll (ViewAppendState newhdl) uhdl)+ commit (set (unitHoodles.currentUnit) uhdl' xstate)+ return ()+ return (Just (Just ())) -- | main pen coordinate adding process -- | now being changed@@ -157,19 +192,31 @@ -> CanvasGeometry -> TempRender (Seq (Double,Double,Double)) -> ((Double,Double),Double) - -> MainCoroutine (Seq (Double,Double,Double))-penProcess cid pnum geometry trdr ((x0,y0),z0) = do + -> UTCTime+ -> MainCoroutine (Maybe (Seq (Double,Double,Double)))+penProcess cid pnum geometry trdr ((x0,y0),z0) ctime = do r <- nextevent- xst <- get - forBoth' unboxBiAct (fsingle r xst) . getCanvasInfo cid $ xst+ ntime <- liftIO getCurrentTime+ let ispressandhold = + abs (toRational (diffUTCTime ctime ntime)) > 1 % 2+ lst = (toList . tempInfo) trdr+ deltax = let xlst = map (\(x,_,_)->x) lst+ in abs (maximum xlst - minimum xlst)+ deltay = let ylst = map (\(_,y,_)->y) lst+ in abs (maximum ylst - minimum ylst)+ -- temporarily fix the range+ if (deltax < 20 && deltay < 20 && ispressandhold && Prelude.length lst < 20) + then return Nothing + else do xst <- get + forBoth' unboxBiAct (fsingle r xst) . (getCanvasInfo cid . view (unitHoodles.currentUnit)) $ xst where pdraw = tempInfo trdr fsingle :: forall b. UserEvent -> HoodleState -> CanvasInfo b - -> MainCoroutine (Seq (Double,Double,Double))+ -> MainCoroutine (Maybe (Seq (Double,Double,Double))) fsingle r xstate cvsInfo = penMoveAndUpOnly r pnum geometry - (penProcess cid pnum geometry trdr ((x0,y0),z0))+ (penProcess cid pnum geometry trdr ((x0,y0),z0) ctime) (\(pcoord,(x,y)) -> do let PointerCoord _ _ _ z = pcoord let pinfo = view penInfo xstate@@ -183,8 +230,8 @@ liftIO $ doubleBufferFlush tgtsfc cvsInfo --- let ntrdr = trdr { tempInfo = pdraw |> (x,y,z) }- penProcess cid pnum geometry ntrdr ((x,y),z) )- (\_ -> return pdraw )+ penProcess cid pnum geometry ntrdr ((x,y),z) ctime)+ (\_ -> return (Just pdraw)) -- | skipIfNotInSamePage :: Monad m =>
src/Hoodle/Coroutine/Scroll.hs view
@@ -1,11 +1,14 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE Rank2Types #-} {-# LANGUAGE ScopedTypeVariables #-} + ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Coroutine.Scroll -- Copyright : (c) 2011-2014 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -18,6 +21,7 @@ import Control.Monad import Control.Monad.State import Control.Monad.Trans.Either+-- import qualified Graphics.UI.Gtk as Gtk -- from hoodle-platform import Control.Monad.Trans.Crtn import Data.Functor.Identity (Identity(..))@@ -36,15 +40,30 @@ import Hoodle.View.Coordinate -- +-- |+updateCanvasInfo :: (forall a. CanvasInfo a -> CanvasInfo a) -> CanvasId -> MainCoroutine ()+updateCanvasInfo f cid = pureUpdateUhdl $ \uhdl -> + let cinfobox = getCanvasInfo cid uhdl+ ncinfobox = (runIdentity . forBoth unboxBiXform (return . f)) cinfobox+ in setCanvasInfo (cid,ncinfobox) uhdl++-- |+updateCanvasInfo2 :: (CanvasInfo SinglePage -> CanvasInfo SinglePage) + -> (CanvasInfo ContinuousPage -> CanvasInfo ContinuousPage)+ -> CanvasId+ -> MainCoroutine ()+updateCanvasInfo2 fs fc cid = + pureUpdateUhdl $ \uhdl ->+ let cinfobox = getCanvasInfo cid uhdl+ ncinfobox = (runIdentity . unboxBiXform (return . fs) (return . fc)) cinfobox+ in setCanvasInfo (cid,ncinfobox) uhdl+ -- | moveViewPortBy :: MainCoroutine ()->CanvasId-> ((Double,Double)->(Double,Double)) -> MainCoroutine () moveViewPortBy rndr cid f = - updateXState (return . act) >> adjustScrollbarWithGeometryCvsId cid >> rndr + updateCanvasInfo moveact cid >> adjustScrollbarWithGeometryCvsId cid >> rndr where - act xst = let cinfobox = getCanvasInfo cid xst - ncinfobox = (runIdentity . forBoth unboxBiXform (return . moveact)) cinfobox - in setCanvasInfo (cid,ncinfobox) xst moveact :: CanvasInfo a -> CanvasInfo a moveact cinfo = let BBox (x0,y0) _ = @@ -60,25 +79,19 @@ adjustScrollbarWithGeometryCvsId :: CanvasId -> MainCoroutine () adjustScrollbarWithGeometryCvsId cid = do xstate <- get- let cinfobox = getCanvasInfo cid xstate- geometry <- liftIO (getCanvasGeometryCvsId cid xstate)+ let uhdl = view (unitHoodles.currentUnit) xstate+ cinfobox = getCanvasInfo cid uhdl+ geometry <- liftIO (getCanvasGeometryCvsId cid uhdl) let (hadj,vadj) = view (unboxLens adjustments) cinfobox connidh = view (unboxLens horizAdjConnId) cinfobox connidv = view (unboxLens vertAdjConnId) cinfobox- liftIO $ A.adjustScrollbarWithGeometry geometry ((hadj,connidh),(vadj,connidv)) + doIOaction_ $ A.adjustScrollbarWithGeometry geometry ((hadj,connidh),(vadj,connidv)) -- | adjustScrollbarWithGeometryCurrent :: MainCoroutine ()-adjustScrollbarWithGeometryCurrent = adjustScrollbarWithGeometryCvsId . view (currentCanvas._1) =<< get -{- xstate <- get- geometry <- liftIO . getGeometry4CurrCvs $ xstate- let cinfobox = view currentCanvasInfo xstate- let (hadj,vadj) = unboxGet adjustments cinfobox - connidh = unboxGet horizAdjConnId cinfobox - connidv = unboxGet vertAdjConnId cinfobox- liftIO $ A.adjustScrollbarWithGeometry geometry ((hadj,connidh),(vadj,connidv)) --}+adjustScrollbarWithGeometryCurrent = adjustScrollbarWithGeometryCvsId . view (currentCanvas._1) + . view (unitHoodles.currentUnit) =<< get -- | hscrollBarMoved :: CanvasId -> Double -> MainCoroutine () @@ -97,13 +110,13 @@ chkCvsIdNInvalidate cid vscrollMove cid v - -- | vscrollMove :: CanvasId -> Double -> MainCoroutine () vscrollMove cid v0 = do ev <- nextevent xst <- get - geometry <- liftIO (getCanvasGeometryCvsId cid xst)+ let uhdl = view (unitHoodles.currentUnit) xst+ geometry <- liftIO (getCanvasGeometryCvsId cid uhdl) case ev of VScrollBarMoved cid' v -> do when (cid /= cid') $ @@ -119,37 +132,25 @@ VScrollBarStart cid' v -> vscrollStart cid' v _ -> return () -- -- | smoothScroll :: CanvasId -> CanvasGeometry -> Double -> Double -> MainCoroutine () -smoothScroll cid geometry v0 v = do - xst <- get - let b = view (settings.doesSmoothScroll) xst - let diff = (v - v0) - lst' | (diff < 20 && diff > -20) = [v]- | (diff < 5 &&diff > -5) = []- | otherwise = let m :: Int = floor (minimum [20, (abs diff) / 10.0])- delta = diff / fromIntegral m - in [v0 + fromIntegral n*delta | n <- [1..m] ]- lst | b = lst' - | otherwise = [v] +smoothScroll cid geometry _v0 v = do + -- xst <- get + let lst = [v] forM_ lst $ \v' -> do - updateXState $ return . over currentCanvasInfo - (runIdentity - . unboxBiXform (Identity . scrollmovecanvas v) - (Identity . scrollmovecanvasCont geometry v') )+ -- updateXState $ return . updater + updateCanvasInfo2 (scrollmovecanvas v) (scrollmovecanvasCont geometry v') cid invalidateInBBox Nothing Efficient cid - where scrollmovecanvas vv cvsInfo = - let BBox vm_orig _ = unViewPortBBox $ view (viewInfo.pageArrangement.viewPortBBox) cvsInfo- in over (viewInfo.pageArrangement.viewPortBBox) - (apply (moveBBoxULCornerTo (fst vm_orig,vv))) cvsInfo - -- - scrollmovecanvasCont geom vv cvsInfo = - let BBox vm_orig _ = unViewPortBBox $ view (viewInfo.pageArrangement.viewPortBBox) cvsInfo- cpn = PageNum . view currentPageNum $ cvsInfo - ncpn = maybe cpn fst $ desktop2Page geom (DeskCoord (0,vv))- in over currentPageNum (const (unPageNum ncpn)) - . over (viewInfo.pageArrangement.viewPortBBox) - (apply (moveBBoxULCornerTo (fst vm_orig,vv))) $ cvsInfo -+ where + scrollmovecanvas vv cvsInfo = + let BBox vm_orig _ = unViewPortBBox $ view (viewInfo.pageArrangement.viewPortBBox) cvsInfo+ in over (viewInfo.pageArrangement.viewPortBBox) + (apply (moveBBoxULCornerTo (fst vm_orig,vv))) cvsInfo + -- + scrollmovecanvasCont geom vv cvsInfo = + let BBox vm_orig _ = unViewPortBBox $ view (viewInfo.pageArrangement.viewPortBBox) cvsInfo+ cpn = PageNum . view currentPageNum $ cvsInfo + ncpn = maybe cpn fst $ desktop2Page geom (DeskCoord (0,vv))+ in over currentPageNum (const (unPageNum ncpn)) + . over (viewInfo.pageArrangement.viewPortBBox) + (apply (moveBBoxULCornerTo (fst vm_orig,vv))) $ cvsInfo
src/Hoodle/Coroutine/Select.hs view
@@ -3,9 +3,9 @@ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Coroutine.Select --- Copyright : (c) 2011-2014 Ian-Woo Kim+-- Copyright : (c) 2011-2015 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -18,8 +18,8 @@ -- from other package import Control.Applicative-import Control.Category-import Control.Lens (view,set)+-- import Control.Category+import Control.Lens (view,set,(.~),(^.)) import Control.Monad import Control.Monad.Identity import Control.Monad.State@@ -47,6 +47,7 @@ import Hoodle.Coroutine.Draw import Hoodle.Coroutine.Mode import Hoodle.Coroutine.Pen+import Hoodle.Coroutine.Select.Clipboard import Hoodle.ModelAction.Layer import Hoodle.ModelAction.Page import Hoodle.ModelAction.Pen@@ -62,21 +63,21 @@ import Hoodle.View.Coordinate import Hoodle.View.Draw -- -import Prelude hiding ((.), id)+-- import Prelude hiding ((.), id) -- | For Selection mode from pen mode with 2nd pen button dealWithOneTimeSelectMode :: MainCoroutine () -- ^ main action -> MainCoroutine () -- ^ terminating action -> MainCoroutine () dealWithOneTimeSelectMode action terminator = do - xstate <- get - case view isOneTimeSelectMode xstate of + uhdl <- view (unitHoodles.currentUnit) <$> get + case view isOneTimeSelectMode uhdl of NoOneTimeSelectMode -> action YesBeforeSelect -> - action >> updateXState (return . set isOneTimeSelectMode YesAfterSelect)+ action >> pureUpdateUhdl (isOneTimeSelectMode .~ YesAfterSelect) YesAfterSelect -> do terminator - updateXState (return . set isOneTimeSelectMode NoOneTimeSelectMode) + pureUpdateUhdl (isOneTimeSelectMode .~ NoOneTimeSelectMode) modeChange ToViewAppendMode @@ -90,20 +91,23 @@ -> MainCoroutine () commonSelectStart typ pbtn cid = case typ of SelectHandToolWork -> (\_ -> return ())- _ -> commonPenStart selectaction cid- where selectaction cinfo pnum geometry (x,y) = do+ _ -> commonPenStart selectaction cid >=> const (return ())++ where selectaction cinfo pnum geometry (x,y) _ = do itms <- rItmsInCurrLyr ctime <- liftIO $ getCurrentTime let newSelectAction _page = dealWithOneTimeSelectMode (do tsel <- createTempRender geometry [] case typ of - SelectRectangleWork -> + SelectRectangleWork -> do newSelectRectangle cid pnum geometry itms (x,y) ((x,y),ctime) tsel- SelectLassoWork -> + return ()+ SelectLassoWork -> do newSelectLasso cinfo pnum geometry itms (x,y) ((x,y),ctime) (Sq.empty |> (x,y)) tsel+ return () _ -> return () Cairo.surfaceFinish (tempSurfaceSrc tsel) showContextMenu (pnum,(x,y))@@ -111,9 +115,9 @@ (return ()) action (Right tpage) | hitInHandle tpage (x,y) = do let doesKeepRatio = case pbtn of - PenButton1 -> True- PenButton3 -> False- _ -> False+ PenButton1 -> True+ PenButton3 -> False+ _ -> False case getULBBoxFromSelected tpage of Middle bbox -> maybe (return ()) @@ -131,8 +135,8 @@ _ -> return () action (Right tpage) | otherwise = newSelectAction (hPage2RPage tpage) action (Left page) = newSelectAction page- xstate <- get - let hdlmodst = view hoodleModeState xstate + uhdl <- view (unitHoodles.currentUnit) <$> get + let hdlmodst = view hoodleModeState uhdl let epage = getCurrentPageEitherFromHoodleModeState cinfo hdlmodst action epage @@ -155,13 +159,12 @@ (prev,otime) tempselection = do r <- nextevent xst <- get - forBoth' unboxBiAct (fsingle r xst) . getCanvasInfo cid $ xst+ cache <- renderCache+ forBoth' unboxBiAct (fsingle r xst cache) . getCanvasInfo cid . view (unitHoodles.currentUnit) $ xst where - fsingle r xstate cinfo = penMoveAndUpOnly r pnum geometry defact- (moveact xstate cinfo) (upact xstate cinfo)- defact = newSelectRectangle cid pnum geometry itms orig - (prev,otime) tempselection - moveact xstate _cinfo (_pcoord,(x,y)) = do + fsingle r xstate cache cinfo = penMoveAndUpOnly r pnum geometry defact (moveact cache) (upact xstate cinfo)+ defact = newSelectRectangle cid pnum geometry itms orig (prev,otime) tempselection + moveact cache (_pcoord,(x,y)) = do let bbox = BBox orig (x,y) hittestbbox = hltEmbeddedByBBox bbox itms hitteditms = takeHitted hittestbbox@@ -171,17 +174,16 @@ when ((not.null) fitms || (not.null) sitms) $ do let xformfunc = cairoXform4PageCoordinate (mkXform4Page geometry pnum) ulbbox = unUnion . mconcat . fmap (Union .Middle . flip inflate 5 . getBBox) $ fitms- cache = view renderCache xstate xform = mkXform4Page geometry pnum renderfunc = do xformfunc case ulbbox of Top -> do - cairoRenderOption (InBBoxOption Nothing) cache (InBBox page, Just xform) + cairoRenderOption (InBBoxOption Nothing) cache cid (InBBox page, Just xform) mapM_ renderSelectedItem hitteditms Middle sbbox -> do let redrawee = filter (do2BBoxIntersect sbbox.getBBox) hitteditms - cairoRenderOption (InBBoxOption (Just sbbox)) cache (InBBox page, Just xform)+ cairoRenderOption (InBBoxOption (Just sbbox)) cache cid (InBBox page, Just xform) clipBBox (Just sbbox) mapM_ renderSelectedItem redrawee Bottom -> return ()@@ -197,12 +199,13 @@ let (_,(x,y)) = runIdentity $ skipIfNotInSamePage pnum geometry pcoord (return (pcoord,prev)) return- epage = getCurrentPageEitherFromHoodleModeState cinfo (view hoodleModeState xstate)+ uhdl = view (unitHoodles.currentUnit) xstate+ epage = getCurrentPageEitherFromHoodleModeState cinfo (view hoodleModeState uhdl) cpn = view currentPageNum cinfo bbox = BBox orig (x,y) hittestbbox = hltEmbeddedByBBox bbox itms selectitms = fmapAL unNotHitted id hittestbbox- SelectState thdl = view hoodleModeState xstate+ SelectState thdl = view hoodleModeState uhdl newpage = case epage of Left pagebbox -> makePageSelectMode pagebbox selectitms Right tpage -> @@ -212,9 +215,10 @@ in npage newthdl = set gselSelected (Just (cpn,newpage)) thdl ui = view gtkUIManager xstate- liftIO $ toggleCutCopyDelete ui (isAnyHitted selectitms)- put . set hoodleModeState (SelectState newthdl) - =<< (liftIO (updatePageAll (SelectState newthdl) xstate))+ liftIO $ toggleCutCopyDelete ui (isAnyHitted selectitms)+ uhdl' <- liftIO (updatePageAll (SelectState newthdl) uhdl)+ pureUpdateUhdl (const ((hoodleModeState .~ SelectState newthdl) uhdl'))+ commit_ invalidateAllInBBox Nothing Efficient @@ -226,8 +230,8 @@ -> Page SelectMode -> MainCoroutine () startMoveSelect cid pnum geometry ((x,y),ctime) tpage = do- cache <- view renderCache <$> get- itmimage <- liftIO $ mkItmsNImg cache tpage+ cache <- renderCache+ itmimage <- liftIO $ mkItmsNImg cache cid tpage tsel <- createTempRender geometry itmimage moveSelect cid pnum geometry (x,y) ((x,y),ctime) tsel Cairo.surfaceFinish (tempSurfaceSrc tsel)@@ -246,21 +250,20 @@ moveSelect cid pnum geometry orig@(x0,y0) (prev,otime) tempselection = do xst <- get+ let uhdl = view (unitHoodles.currentUnit) xst r <- nextevent - forBoth' unboxBiAct (fsingle r xst) . getCanvasInfo cid $ xst + forBoth' unboxBiAct (fsingle r uhdl) (getCanvasInfo cid uhdl) where - fsingle r xstate cinfo = - penMoveAndUpInterPage r pnum geometry defact (moveact xstate cinfo) (upact xstate cinfo) - defact = moveSelect cid pnum geometry orig (prev,otime) - tempselection- moveact _xstate _cinfo oldpgn pcpair@(newpgn,PageCoord (px,py)) = do + fsingle r uhdl cinfo = + penMoveAndUpInterPage r pnum geometry defact moveact (upact uhdl cinfo) + defact = moveSelect cid pnum geometry orig (prev,otime) tempselection+ moveact oldpgn pcpair@(newpgn,PageCoord (px,py)) = do let (x,y) | oldpgn == newpgn = (px,py) | otherwise = let DeskCoord (xo,yo) = page2Desktop geometry (oldpgn,PageCoord (0,0)) DeskCoord (xn,yn) = page2Desktop geometry pcpair in (xn-xo,yn-yo)- (willUpdate,(ncoord,ntime)) <- liftIO $ getNewCoordTime (prev,otime) (x,y) when willUpdate $ do let sfunc = offsetFunc (x-x0,y-y0)@@ -275,25 +278,25 @@ invalidateTempBasePage cid (tempSurfaceSrc tempselection) pnum (drawTempSelectImage geometry tempselection xformmat) moveSelect cid pnum geometry orig (ncoord,ntime) tempselection- upact :: HoodleState -> CanvasInfo a -> PointerCoord -> MainCoroutine () - upact xst cinfo pcoord = + upact :: UnitHoodle -> CanvasInfo a -> PointerCoord -> MainCoroutine () + upact uhdl cinfo pcoord = switchActionEnteringDiffPage pnum geometry pcoord (return ()) - (chgaction xst cinfo) - (ordaction xst cinfo)- chgaction :: HoodleState -> CanvasInfo a -> PageNum -> (PageNum,PageCoordinate) -> MainCoroutine () - chgaction xstate cinfo oldpgn (newpgn,PageCoord (x,y)) = do - let hdlmodst@(SelectState thdl) = view hoodleModeState xstate+ (chgaction uhdl cinfo) + (ordaction uhdl cinfo)+ chgaction :: UnitHoodle -> CanvasInfo a + -> PageNum -> (PageNum,PageCoordinate) -> MainCoroutine () + chgaction uhdl cinfo oldpgn (newpgn,PageCoord (x,y)) = do + let hdlmodst@(SelectState thdl) = view hoodleModeState uhdl epage = getCurrentPageEitherFromHoodleModeState cinfo hdlmodst- cache = view renderCache xstate- (xstate1,nthdl1,selecteditms) <- + cvsid = view canvasId cinfo+ (uhdl1,nthdl1,selecteditms) <- case epage of Right oldtpage -> do let itms = getSelectedItms oldtpage let oldtpage' = deleteSelected oldtpage- nthdl <- liftIO $ updateTempHoodleSelectIO cache thdl oldtpage' (unPageNum oldpgn)- xst <- return . set hoodleModeState (SelectState nthdl)- =<< (liftIO (updatePageAll (SelectState nthdl) xstate)) - return (xst,nthdl,itms) + nthdl <- updateTempHoodleSelectM cvsid thdl oldtpage' (unPageNum oldpgn)+ uhdl' <- liftIO (updatePageAll (SelectState nthdl) uhdl)+ return (uhdl',nthdl,itms) Left _ -> error "this is impossible, in moveSelect" let maction = do page <- M.lookup (unPageNum newpgn) (view gselAll nthdl1)@@ -303,35 +306,32 @@ alist = olditms :- Hitted newitms :- Empty ntpage = makePageSelectMode page alist coroutineaction = do - nthdl2 <- liftIO $ updateTempHoodleSelectIO cache nthdl1 ntpage (unPageNum newpgn) - let cibox = view currentCanvasInfo xstate1 - ncibox = (runIdentity . forBoth unboxBiXform (return . set currentPageNum (unPageNum newpgn))) - cibox - cmap = getCanvasInfoMap xstate1 - cmap' = M.adjust (const ncibox) cid cmap - xst = maybe xstate1 id $ setCanvasInfoMap cmap' xstate1- return . set hoodleModeState (SelectState nthdl2)- =<< (liftIO (updatePageAll (SelectState nthdl2) xst)) + nthdl2 <- updateTempHoodleSelectM cvsid nthdl1 ntpage (unPageNum newpgn) + -- let cibox = view currentCanvasInfo uhdl1 + -- ncibox = ( runIdentity + -- . forBoth unboxBiXform (return . set currentPageNum (unPageNum newpgn))) + -- cibox + liftIO (updatePageAll (SelectState nthdl2) uhdl1) return coroutineaction- xstate2 <- maybe (return xstate1) id maction - commit xstate2- -- invalidateAll + uhdl2 <- maybe (return uhdl1) id maction+ pureUpdateUhdl (const uhdl2)+ commit_ invalidateAllInBBox Nothing Efficient ----- ordaction xstate cinfo _pgn (_cpn,PageCoord (x,y)) = do + ordaction uhdl cinfo _pgn (_cpn,PageCoord (x,y)) = do let offset = (x-x0,y-y0)- hdlmodst@(SelectState thdl) = view hoodleModeState xstate+ hdlmodst@(SelectState thdl) = view hoodleModeState uhdl epage = getCurrentPageEitherFromHoodleModeState cinfo hdlmodst pagenum = view currentPageNum cinfo+ cvsid = view canvasId cinfo case epage of Right tpage -> do let newtpage = changeSelectionByOffset offset tpage- cache = view renderCache xstate- newthdl <- liftIO $ updateTempHoodleSelectIO cache thdl newtpage pagenum - commit . set hoodleModeState (SelectState newthdl)- =<< (liftIO (updatePageAll (SelectState newthdl) xstate))+ newthdl <- updateTempHoodleSelectM cvsid thdl newtpage pagenum + uhdl' <- liftIO (updatePageAll (SelectState newthdl) uhdl)+ pureUpdateUhdl (const uhdl')+ commit_ Left _ -> error "this is impossible, in moveSelect" - -- invalidateAll invalidateAllInBBox Nothing Efficient @@ -347,8 +347,8 @@ -> MainCoroutine () startResizeSelect doesKeepRatio handle cid pnum geometry bbox ((x,y),ctime) tpage = do- cache <- view renderCache <$> get - itmimage <- liftIO $ mkItmsNImg cache tpage + cache <- renderCache+ itmimage <- liftIO $ mkItmsNImg cache cid tpage tsel <- createTempRender geometry itmimage resizeSelect doesKeepRatio handle cid pnum geometry bbox ((x,y),ctime) tsel @@ -370,12 +370,12 @@ resizeSelect doesKeepRatio handle cid pnum geometry origbbox (prev,otime) tempselection = do xst <- get+ let uhdl = view (unitHoodles.currentUnit) xst r <- nextevent - forBoth' unboxBiAct (fsingle r xst) . getCanvasInfo cid $ xst+ forBoth' unboxBiAct (fsingle r uhdl) . getCanvasInfo cid $ uhdl where- fsingle r xstate cinfo = penMoveAndUpOnly r pnum geometry defact moveact (upact xstate cinfo)- defact = resizeSelect doesKeepRatio handle cid pnum geometry - origbbox (prev,otime) tempselection+ fsingle r uhdl cinfo = penMoveAndUpOnly r pnum geometry defact moveact (upact uhdl cinfo)+ defact = resizeSelect doesKeepRatio handle cid pnum geometry origbbox (prev,otime) tempselection moveact (_pcoord,(x,y)) = do (willUpdate,(ncoord,ntime)) <- liftIO $ getNewCoordTime (prev,otime) (x,y) when willUpdate $ do @@ -393,20 +393,16 @@ | otherwise -> newbbox' else newbbox' sfunc = scaleFromToBBox origbbox newbbox- xform = unCvsCoord . desktop2Canvas geometry- . page2Desktop geometry . (,) pnum . PageCoord+ xform = unCvsCoord . desktop2Canvas geometry . page2Desktop geometry . (,) pnum . PageCoord (c1,c2) = xform (sfunc (0,0)) (a1',a2') = xform (sfunc (1,0)) (a1,a2) = (a1'-c1,a2'-c2) (b1',b2') = xform (sfunc (0,1)) (b1,b2) = (b1'-c1,b2'-c2) xformmat = Mat.Matrix a1 a2 b1 b2 c1 c2 - invalidateTemp cid (tempSurfaceSrc tempselection) - (drawTempSelectImage geometry tempselection - xformmat)- resizeSelect doesKeepRatio handle cid pnum geometry - origbbox (ncoord,ntime) tempselection- upact xstate cinfo pcoord = do + invalidateTemp cid (tempSurfaceSrc tempselection) (drawTempSelectImage geometry tempselection xformmat)+ resizeSelect doesKeepRatio handle cid pnum geometry origbbox (ncoord,ntime) tempselection+ upact uhdl cinfo pcoord = do let (_,(x,y)) = runIdentity $ skipIfNotInSamePage pnum geometry pcoord (return (pcoord,prev)) return@@ -423,19 +419,19 @@ | handle == HandleBR -> BBox (x0,y0) (x1,y0+(x1-x0)*r) | otherwise -> newbbox' else newbbox' - hdlmodst@(SelectState thdl) = view hoodleModeState xstate+ hdlmodst@(SelectState thdl) = view hoodleModeState uhdl epage = getCurrentPageEitherFromHoodleModeState cinfo hdlmodst pagenum = view currentPageNum cinfo+ cvsid = view canvasId cinfo case epage of Right tpage -> do let sfunc = scaleFromToBBox origbbox newbbox newtpage = changeSelectionBy sfunc tpage - cache = view renderCache xstate- newthdl <- liftIO $ updateTempHoodleSelectIO cache thdl newtpage pagenum - commit . set hoodleModeState (SelectState newthdl)- =<< (liftIO (updatePageAll (SelectState newthdl) xstate))+ newthdl <- updateTempHoodleSelectM cvsid thdl newtpage pagenum + uhdl' <- liftIO (updatePageAll (SelectState newthdl) uhdl)+ pureUpdateUhdl (const uhdl')+ commit_ Left _ -> error "this is impossible, in resizeSelect" - -- invalidateAll invalidateAllInBBox Nothing Efficient return () @@ -443,50 +439,50 @@ -- | selectPenColorChanged :: PenColor -> MainCoroutine () selectPenColorChanged pcolor = do - xstate <- get- let SelectState thdl = view hoodleModeState xstate - Just (n,tpage) = view gselSelected thdl- slayer = view (glayers.selectedLayer) tpage- case unTEitherAlterHitted . view gitems $ slayer of - Left _ -> return () - Right alist -> do - let alist' = fmapAL id - (Hitted . map (changeItemStrokeColor pcolor) . unHitted) alist- newlayer = Right alist'- newpage = set (glayers.selectedLayer) (GLayer (view gbuffer slayer) (TEitherAlterHitted newlayer)) tpage - cache = view renderCache xstate- newthdl <- liftIO $ updateTempHoodleSelectIO cache thdl newpage n- commit =<< liftIO (updatePageAll (SelectState newthdl)- . set hoodleModeState (SelectState newthdl) $ xstate )- -- invalidateAll - invalidateAllInBBox Nothing Efficient+ uhdl <- view (unitHoodles.currentUnit) <$> get + let cid = getCurrentCanvasId uhdl+ SelectState thdl = view hoodleModeState uhdl+ Just (n,tpage) = view gselSelected thdl+ slayer = view (glayers.selectedLayer) tpage+ case unTEitherAlterHitted . view gitems $ slayer of + Left _ -> return () + Right alist -> do + let alist' = fmapAL id (Hitted . map (changeItemStrokeColor pcolor) . unHitted) alist+ newlayer = Right alist'+ newpage = (glayers.selectedLayer .~ (GLayer (slayer^.gbuffer) (TEitherAlterHitted newlayer))) tpage + newthdl <- updateTempHoodleSelectM cid thdl newpage n+ uhdl' <- liftIO (updatePageAll (SelectState newthdl) uhdl)+ pureUpdateUhdl (const uhdl')+ commit_+ invalidateAllInBBox Nothing Efficient -- | selectPenWidthChanged :: Double -> MainCoroutine () selectPenWidthChanged pwidth = do - xstate <- get- let SelectState thdl = view hoodleModeState xstate + xst <- get+ let uhdl = view (unitHoodles.currentUnit) xst+ cid = getCurrentCanvasId uhdl+ SelectState thdl = view hoodleModeState uhdl Just (n,tpage) = view gselSelected thdl slayer = view (glayers.selectedLayer) tpage- cache = view renderCache xstate- case unTEitherAlterHitted . view gitems $ slayer of + case (unTEitherAlterHitted . view gitems) slayer of Left _ -> return () Right alist -> do let alist' = fmapAL id (Hitted . map (changeItemStrokeWidth pwidth) . unHitted) alist newlayer = Right alist' newpage = set (glayers.selectedLayer) (GLayer (view gbuffer slayer) (TEitherAlterHitted newlayer)) tpage- newthdl <- liftIO $ updateTempHoodleSelectIO cache thdl newpage n - commit =<< liftIO (updatePageAll (SelectState newthdl) - . set hoodleModeState (SelectState newthdl) $ xstate )- -- invalidateAll + newthdl <- updateTempHoodleSelectM cid thdl newpage n + uhdl' <- liftIO (updatePageAll (SelectState newthdl) uhdl)+ pureUpdateUhdl (const uhdl')+ commit_ invalidateAllInBBox Nothing Efficient -- | main mouse pointer click entrance in lasso selection mode. -- choose either starting new rectangular selection or move previously -- selected selection. selectLassoStart :: PenButton -> CanvasId -> PointerCoord -> MainCoroutine ()-selectLassoStart = commonSelectStart SelectLassoWork+selectLassoStart p cid coord = commonSelectStart SelectLassoWork p cid coord >> return () -- | @@ -501,23 +497,19 @@ -> MainCoroutine () newSelectLasso cvsInfo pnum geometry itms orig (prev,otime) lasso tsel = nextevent >>= flip fsingle cvsInfo where - fsingle r cinfo = penMoveAndUpOnly r pnum geometry defact- (moveact cinfo) (upact cinfo)+ fsingle r cinfo = penMoveAndUpOnly r pnum geometry defact (moveact cinfo) (upact cinfo) defact = newSelectLasso cvsInfo pnum geometry itms orig (prev,otime) lasso tsel moveact cinfo (_pcoord,(x,y)) = do let nlasso = lasso |> (x,y) (willUpdate,(ncoord,ntime)) <- liftIO $ getNewCoordTime (prev,otime) (x,y)- when willUpdate $ do - invalidateTemp (view canvasId cinfo) (tempSurfaceSrc tsel) (renderLasso geometry nlasso) + when willUpdate $ invalidateTemp (view canvasId cinfo) (tempSurfaceSrc tsel) (renderLasso geometry nlasso) newSelectLasso cinfo pnum geometry itms orig (ncoord,ntime) nlasso tsel upact cinfo pcoord = do - xstate <- get - let (_,(x,y)) = runIdentity $ - skipIfNotInSamePage pnum geometry pcoord - (return (pcoord,prev)) return+ uhdl <- view (unitHoodles.currentUnit) <$> get + let (_,(x,y)) = runIdentity $ skipIfNotInSamePage pnum geometry pcoord (return (pcoord,prev)) return nlasso = lasso |> (x,y)- hdlmodst = view hoodleModeState xstate + hdlmodst = view hoodleModeState uhdl epage = getCurrentPageEitherFromHoodleModeState cinfo hdlmodst cpn = view currentPageNum cinfo hittestlasso1 = hltFilteredBy (hitLassoItem (nlasso |> orig)) itms@@ -530,7 +522,7 @@ selectitms | (not.null) selecteditms1 = selectitms1 | otherwise = selectitms2- SelectState thdl = view hoodleModeState xstate+ SelectState thdl = view hoodleModeState uhdl newpage = case epage of Left pagebbox -> let currlayer= getCurrentLayer pagebbox@@ -544,11 +536,11 @@ npage = set (glayers.selectedLayer) newlayer tpage in npage newthdl = set gselSelected (Just (cpn,newpage)) thdl - let ui = view gtkUIManager xstate+ ui <- view gtkUIManager <$> get liftIO $ toggleCutCopyDelete ui (isAnyHitted selectitms)- put . set hoodleModeState (SelectState newthdl) - =<< (liftIO (updatePageAll (SelectState newthdl) xstate))- -- invalidateAll + uhdl' <- liftIO (updatePageAll (SelectState newthdl) uhdl)+ pureUpdateUhdl (const ((hoodleModeState .~ SelectState newthdl) uhdl'))+ commit_ invalidateAllInBBox Nothing Efficient
src/Hoodle/Coroutine/Select/Clipboard.hs view
@@ -3,9 +3,9 @@ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Coroutine.Select.Clipboard --- Copyright : (c) 2011-2014 Ian-Woo Kim+-- Copyright : (c) 2011-2015 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -18,14 +18,17 @@ -- from other packages import Control.Applicative-import Control.Lens (view,set,(%~))-import Control.Monad.State -import Graphics.UI.Gtk hiding (get,set)+import Control.Lens (view,set,(.~))+import Control.Monad.State+import Control.Monad.Trans.Maybe+import qualified Data.Foldable as F+import Data.Maybe (fromMaybe)+import qualified Graphics.UI.Gtk as Gtk -- from hoodle-platform -import Control.Monad.Trans.Crtn.Queue import Data.Hoodle.Generic import Data.Hoodle.Select-import Data.Hoodle.Simple+import Data.Hoodle.Simple (Item(..))+import Graphics.Hoodle.Render import Graphics.Hoodle.Render.Item import Graphics.Hoodle.Render.Type import Graphics.Hoodle.Render.Type.HitTest@@ -33,22 +36,38 @@ import Hoodle.Accessor import Hoodle.Coroutine.Draw import Hoodle.Coroutine.Commit -import Hoodle.Coroutine.Mode +import Hoodle.Coroutine.Mode+import Hoodle.Coroutine.Page import Hoodle.ModelAction.Page import Hoodle.ModelAction.Select import Hoodle.ModelAction.Select.Transform import Hoodle.ModelAction.Clipboard+import Hoodle.Type.Alias import Hoodle.Type.Canvas import Hoodle.Type.Coroutine import Hoodle.Type.Event import Hoodle.Type.PageArrangement import Hoodle.Type.HoodleState ++-- |+updateTempHoodleSelectM :: CanvasId+ -> Hoodle SelectMode + -> Page SelectMode + -> Int+ -> MainCoroutine (Hoodle SelectMode)+updateTempHoodleSelectM cid thdl tpage pagenum = do + let newpage = hPage2RPage tpage+ callRenderer_ $ updatePageBuf cid newpage+ return (updateTempHoodleSelect thdl tpage pagenum)+ -- | deleteSelection :: MainCoroutine () deleteSelection = do - xstate <- get- case view hoodleModeState xstate of+ xst <- get+ let uhdl = view (unitHoodles.currentUnit) xst+ cid = getCurrentCanvasId uhdl+ case view hoodleModeState uhdl of SelectState thdl -> do let Just (n,tpage) = view gselSelected thdl slayer = view (glayers.selectedLayer) tpage@@ -57,14 +76,11 @@ Right alist -> do let newlayer = Left . concat . getA $ alist newpage = set (glayers.selectedLayer) (GLayer (view gbuffer slayer) (TEitherAlterHitted newlayer)) tpage - cache = view renderCache xstate- newthdl <- liftIO $ updateTempHoodleSelectIO cache thdl newpage n - newxstate <- liftIO $ updatePageAll (SelectState newthdl) - . set hoodleModeState (SelectState newthdl)- $ xstate - commit newxstate - let ui = view gtkUIManager newxstate+ newthdl <- updateTempHoodleSelectM cid thdl newpage n+ newuhdl <- liftIO . updatePageAll (SelectState newthdl) $ uhdl + let ui = view gtkUIManager xst liftIO $ toggleCutCopyDelete ui False + commit ((unitHoodles.currentUnit .~ newuhdl) xst) modeChange ToViewAppendMode invalidateAll _ -> return ()@@ -80,53 +96,54 @@ copySelection = do updateXState copySelectionAction >> invalidateAll where copySelectionAction xst = - forBoth' unboxBiAct (fsingle xst) . view currentCanvasInfo $ xst- fsingle xstate cinfo = maybe (return xstate) id $ do - let hdlmodst = view hoodleModeState xstate- let epage = getCurrentPageEitherFromHoodleModeState cinfo hdlmodst- eitherMaybe epage `pipe` rItmsInActiveLyr - `pipe` (Right . liftIO . updateClipboard xstate . map rItem2Item . takeHitted)+ forBoth' unboxBiAct (fsingle xst) . view (unitHoodles.currentUnit.currentCanvasInfo) $ xst+ fsingle xst cinfo = do+ r <- runMaybeT $ do + let uhdl = view (unitHoodles.currentUnit) xst+ hdlmodst = view hoodleModeState uhdl+ epage = getCurrentPageEitherFromHoodleModeState cinfo hdlmodst+ pg <- (MaybeT . return . eitherMaybe) epage+ hitted <- (MaybeT . return . eitherMaybe) (rItmsInActiveLyr pg)+ (liftIO . updateClipboard xst . map rItem2Item . takeHitted) hitted+ return (fromMaybe xst r) where eitherMaybe (Left _) = Nothing eitherMaybe (Right a) = Just a - x `pipe` a = x >>= eitherMaybe . a - infixl 6 `pipe` -- | getClipFromGtk :: MainCoroutine (Maybe [Item]) getClipFromGtk = do - let action = mkIOaction $ - \evhandler -> do - hdltag <- liftIO $ atomNew "hoodle"- clipbd <- liftIO $ clipboardGet hdltag- liftIO $ clipboardRequestText clipbd (callback4Clip evhandler)- return (UsrEv ActionOrdered)- modify (tempQueue %~ enqueue action) - go - where go = do r <- nextevent - case r of - GotClipboardContent cnt' -> return cnt' - _ -> go + doIOaction $ \evhandler -> do + hdltag <- liftIO $ Gtk.atomNew "hoodle"+ clipbd <- liftIO $ Gtk.clipboardGet hdltag+ liftIO $ Gtk.clipboardRequestText clipbd (callback4Clip evhandler)+ return (UsrEv ActionOrdered)+ waitSomeEvent (\case GotClipboardContent _ -> True; _ -> False ) >>= \(GotClipboardContent cnt') -> return cnt' -- | pasteToSelection :: MainCoroutine () pasteToSelection = do - mitms <- getClipFromGtk - case mitms of - Nothing -> return () - Just itms -> do - -- - callRenderer $ GotRItems <$> mapM cnstrctRItem itms- RenderEv (GotRItems ritms) <- - waitSomeEvent (\case RenderEv (GotRItems _) -> True; _ -> False)- --- modeChange ToSelectMode >>updateXState (pasteAction ritms) >> invalidateAll + mitms <- getClipFromGtk+ F.forM_ mitms $ \itms -> do+ callRenderer $ GotRItems <$> mapM cnstrctRItem itms+ RenderEv (GotRItems ritms) <- + waitSomeEvent (\case RenderEv (GotRItems _) -> True; _ -> False)+ xst <- get+ cache <- renderCache + let ui = view gtkUIManager xst+ modeChange ToSelectMode + updateUhdl (pasteAction cache ui ritms)+ commit_ + canvasZoomUpdateAll+ invalidateAll where - pasteAction itms xst = forBoth' unboxBiAct (fsimple itms xst) . view currentCanvasInfo $ xst- fsimple itms xstate cinfo = do - geometry <- liftIO (getGeometry4CurrCvs xstate)- let pagenum = view currentPageNum cinfo - hdlmodst@(SelectState thdl) = view hoodleModeState xstate+ pasteAction cache ui itms uhdl = forBoth' unboxBiAct (fsimple cache ui itms uhdl) + . view currentCanvasInfo $ uhdl+ fsimple _cache ui itms uhdl cinfo = do + geometry <- liftIO (getGeometry4CurrCvs uhdl)+ let cid = view canvasId cinfo+ pagenum = view currentPageNum cinfo + hdlmodst@(SelectState thdl) = view hoodleModeState uhdl nclipitms = adjustItemPosition4Paste geometry (PageNum pagenum) itms epage = getCurrentPageEitherFromHoodleModeState cinfo hdlmodst tpage = either mkHPage id epage@@ -139,12 +156,7 @@ :- Hitted nclipitms :- Empty ) tpage' = set (glayers.selectedLayer) newlayerselect tpage- cache = view renderCache xstate- thdl' <- liftIO $ updateTempHoodleSelectIO cache thdl tpage' pagenum - xstate' <- liftIO $ updatePageAll (SelectState thdl') - . set hoodleModeState (SelectState thdl') - $ xstate - commit xstate' - let ui = view gtkUIManager xstate' + thdl' <- updateTempHoodleSelectM cid thdl tpage' pagenum + uhdl' <- liftIO $ updatePageAll (SelectState thdl') uhdl liftIO $ toggleCutCopyDelete ui True- return xstate' + return uhdl'
src/Hoodle/Coroutine/Select/ManipulateImage.hs view
@@ -4,9 +4,9 @@ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Coroutine.Select.ManipulateImage--- Copyright : (c) 2013, 2014 Ian-Woo Kim+-- Copyright : (c) 2013-2015 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -17,7 +17,7 @@ module Hoodle.Coroutine.Select.ManipulateImage where -import Control.Lens (set, view, _2)+import Control.Lens (set, view, _2, (.~)) import Control.Monad (when) import Control.Monad.State (get) import Control.Monad.Trans (liftIO)@@ -37,6 +37,7 @@ import Hoodle.Coroutine.Commit import Hoodle.Coroutine.Draw import Hoodle.Coroutine.Pen+import Hoodle.Coroutine.Select.Clipboard import Hoodle.Device import Hoodle.ModelAction.Page import Hoodle.ModelAction.Pen@@ -55,10 +56,10 @@ cropImage :: BBoxed Image -> MainCoroutine () cropImage imgbbx = do - liftIO $ putStrLn "cropImage called" xst <- get- let (cid,cinfobox) = view currentCanvas xst - hdlmodst = view hoodleModeState xst+ let uhdl = view (unitHoodles.currentUnit) xst+ (cid,cinfobox) = view currentCanvas uhdl+ hdlmodst = view hoodleModeState uhdl epage = forBoth' unboxBiAct (flip getCurrentPageEitherFromHoodleModeState hdlmodst) cinfobox case hdlmodst of ViewAppendState _ -> return ()@@ -81,7 +82,8 @@ -> MainCoroutine () startCropRect cid imgbbx (thdl,tpage) pcoord0 = do xst <- get- geometry <- liftIO $ getGeometry4CurrCvs xst+ let uhdl = view (unitHoodles.currentUnit) xst+ geometry <- liftIO $ getGeometry4CurrCvs uhdl forM_ ((desktop2Page geometry . device2Desktop geometry) pcoord0) $ \(p0,c0) -> do tsel <- createTempRender geometry (p0, BBox (unPageCoord c0) (unPageCoord c0)) ctime <- liftIO $ getCurrentTime@@ -91,7 +93,7 @@ let pnum = (fst . tempInfo) tsel img = bbxed_content imgbbx obbox = getBBox imgbbx- cache = view renderCache xst+ cvsid = getCurrentCanvasId uhdl when (isBBox2InBBox1 obbox nbbox) $ do mimg' <- liftIO $ createCroppedImage img obbox nbbox forM_ mimg' $ \img' -> do@@ -101,8 +103,9 @@ waitSomeEvent (\case RenderEv (GotRItem _) -> True; _ -> False) -- let ntpage = replaceSelection rimg' tpage- nthdl <- liftIO $ updateTempHoodleSelectIO cache thdl ntpage (unPageNum pnum)- commit . set hoodleModeState (SelectState nthdl) =<< (liftIO (updatePageAll (SelectState nthdl) xst))+ nthdl <- updateTempHoodleSelectM cvsid thdl ntpage (unPageNum pnum)+ uhdl' <- liftIO (updatePageAll (SelectState nthdl) uhdl)+ commit $ (unitHoodles.currentUnit .~ uhdl') xst invalidateAllInBBox Nothing Efficient return () @@ -156,11 +159,11 @@ rotateImage :: RotateDir -> BBoxed Image -> MainCoroutine () rotateImage dir imgbbx = do xst <- get- let (_cid,cinfobox) = view currentCanvas xst - hdlmodst = view hoodleModeState xst+ let uhdl = view (unitHoodles.currentUnit) xst+ let (cid,cinfobox) = view currentCanvas uhdl+ hdlmodst = view hoodleModeState uhdl pnum = (PageNum . forBoth' unboxBiAct (view currentPageNum)) cinfobox epage = forBoth' unboxBiAct (flip getCurrentPageEitherFromHoodleModeState hdlmodst) cinfobox- cache = view renderCache xst case hdlmodst of ViewAppendState _ -> return () SelectState thdl -> do @@ -170,14 +173,13 @@ let img = bbxed_content imgbbx mimg' <- liftIO (createRotatedImage dir img (getBBox imgbbx)) forM_ mimg' $ \img' -> do - -- callRenderer $ return . GotRItem =<< cnstrctRItem (ItemImage img') RenderEv (GotRItem rimg') <- waitSomeEvent (\case RenderEv (GotRItem _) -> True; _ -> False)- -- let ntpage = replaceSelection rimg' tpage- nthdl <- liftIO $ updateTempHoodleSelectIO cache thdl ntpage (unPageNum pnum)- commit . set hoodleModeState (SelectState nthdl) =<< (liftIO (updatePageAll (SelectState nthdl) xst))+ nthdl <- updateTempHoodleSelectM cid thdl ntpage (unPageNum pnum)+ uhdl' <- liftIO (updatePageAll (SelectState nthdl) uhdl)+ commit $ (unitHoodles.currentUnit .~ uhdl') xst invalidateAllInBBox Nothing Efficient return ()
+ src/Hoodle/Coroutine/Socket.hs view
@@ -0,0 +1,141 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}++-----------------------------------------------------------------------------+-- |+-- Module : Hoodle.Coroutine.Socket+-- Copyright : (c) 2014, 2015 Ian-Woo Kim+--+-- License : BSD3+-- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>+-- Stability : experimental+-- Portability : GHC+--+-----------------------------------------------------------------------------++module Hoodle.Coroutine.Socket where++import Control.Applicative+import Control.Concurrent+import qualified Control.Exception as E+import Control.Lens (view)+import Control.Monad.IO.Class+import Control.Monad.State+import Control.Monad.Trans.Either+import Control.Monad.Trans.Maybe+import Data.Aeson.Parser+import Data.Aeson.Types+import qualified Data.Attoparsec.ByteString as A+import qualified Data.CaseInsensitive as CI+import Data.Monoid ((<>))+import qualified Data.Text as T+import qualified Data.Text.Encoding as TE+import Data.Time.Clock+import qualified Graphics.UI.Gtk as Gtk+import Network.HTTP.Client.Internal (computeCookieString)+import Network.HTTP.Conduit+import qualified Network.WebSockets as WS+import System.Directory+import System.FilePath ((</>))+--+import Hoodle.Coroutine.Dialog+import Hoodle.Coroutine.Hub.Common+import Hoodle.Script.Hook+import Hoodle.Type.Coroutine+import Hoodle.Type.Event+import Hoodle.Type.Hub+import Hoodle.Type.HoodleState+import Hoodle.Type.Synchronization+import Hoodle.Util+--++data Permission = Owner | Editor | Viewer | Stranger deriving (Show,Eq,Ord,Read)++instance ToJSON Permission where+ toJSON Owner = String "owner"+ toJSON Editor = String "editor"+ toJSON Viewer = String "viewer"+ toJSON Stranger = String "stranger"++instance FromJSON Permission where+ parseJSON (String t) =+ case t of+ "owner" -> return Owner+ "editor" -> return Editor+ "viewer" -> return Viewer+ "stranger" -> return Stranger+ _ -> fail "error in parsing Permission"+ parseJSON _ = fail "error in parsing Permission"++data HoodleWSEvent = HWSOpen { hws_permission :: Permission+ , hws_fileuuid :: T.Text+ , hws_filepath :: T.Text }+ | HWSSync { hws_clientuuid :: T.Text+ , hws_filesyncstatus :: FileSyncStatus+ } + deriving Show++instance ToJSON HoodleWSEvent where+ toJSON HWSOpen {..} = object [ "eventType" .= toJSON ("open" :: T.Text)+ , "permission" .= toJSON hws_permission+ , "fileuuid" .= toJSON hws_fileuuid+ , "filepath" .= toJSON hws_filepath ]+ toJSON HWSSync {..} = object [ "eventType" .= toJSON ("sync" :: T.Text)+ , "clientuuid" .= toJSON hws_clientuuid+ , "filesyncstatus" .= toJSON hws_filesyncstatus+ ]++instance FromJSON HoodleWSEvent where+ parseJSON (Object v) = do+ typ :: T.Text <- v .: "eventType"+ case typ of+ "open" -> HWSOpen <$> v .: "permission" <*> v .: "fileuuid" <*> v .: "filepath" + "sync" -> HWSSync <$> v .: "clientuuid" <*> v .: "filesyncstatus"+ _ -> fail "error in parsing HoodleWSEvent"+ parseJSON _ = fail "error in parsing HoodleWSEvent"++-- |+socketConnect :: MainCoroutine ()+socketConnect = do+ xst <- get+ r <- runMaybeT $ do + hset <- (MaybeT . return) $ view hookSet xst+ hinfo <- (MaybeT . return) (hubInfo hset)+ lift (hoodleWSStart hinfo)+ case r of + Nothing -> okMessageBox "socket connect not successful" >> return ()+ Just _ -> return () +++hoodleWSStart :: HubInfo -> MainCoroutine ()+hoodleWSStart hinfo@HubInfo {..} = do+ hdir <- liftIO $ getHomeDirectory+ let tokfile = hdir </> ".hoodle.d" </> "token.txt"+ prepareToken hinfo tokfile + doIOaction $ \evhandler -> do + forkIO $ (`E.catch` (\(err:: E.SomeException)-> print err >> return ())) $ + withHub hinfo tokfile $ \_manager coojar -> do+ request2' <- parseUrl ("http://" <> hubSocketURL <> ":" <> show hubSocketPort </> hubSocketPath)+ ctime <- liftIO getCurrentTime+ let (bstr,_) = computeCookieString request2' coojar ctime True+ newheaders = [(CI.mk "Cookie",bstr)] + liftIO $ WS.runClientWith hubSocketURL hubSocketPort hubSocketPath WS.defaultConnectionOptions newheaders $ \conn -> forever $ do + txt <- WS.receiveData conn+ runEitherT $ do+ v <- hoistEither $ A.parseOnly json (TE.encodeUtf8 txt)+ o :: HoodleWSEvent <- hoistEither $ parseEither parseJSON v+ lift $ hoodleWSDispatchEvent evhandler hinfo o + return (UsrEv ActionOrdered)++hoodleWSDispatchEvent :: (AllEvent -> IO ()) -> HubInfo -> HoodleWSEvent -> IO ()+hoodleWSDispatchEvent evhandler HubInfo {..} HWSOpen {..} = do+ let urlpath = FileUrl (hubFileRoot </> T.unpack hws_filepath)+ uuid = read (T.unpack hws_fileuuid)+ case hws_permission of+ Owner -> (Gtk.postGUIAsync . evhandler . UsrEv) (OpenLink urlpath Nothing)+ Editor -> (Gtk.postGUIAsync . evhandler . UsrEv) (OpenShared uuid)+ _ -> return ()+hoodleWSDispatchEvent evhandler HubInfo {..} HWSSync {..} = + let clientuuid = read (T.unpack hws_clientuuid) + in (Gtk.postGUIAsync . evhandler . UsrEv) (GotSyncEvent False clientuuid hws_filesyncstatus)
src/Hoodle/Coroutine/TextInput.hs view
@@ -1,14 +1,15 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TupleSections #-}+{-# LANGUAGE CPP #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TupleSections #-} ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Coroutine.TextInput --- Copyright : (c) 2011-2014 Ian-Woo Kim+-- Copyright : (c) 2011-2015 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -18,18 +19,16 @@ module Hoodle.Coroutine.TextInput where import Control.Applicative--- import Control.Concurrent.STM (atomically, newTVar)-import Control.Lens (_1,_2,_3,view,set,(%~),(^.),(.~))+import qualified Control.Exception+import Control.Lens (_2,_3,view,(%~),(^.),(.~)) import Control.Monad.State hiding (mapM_, forM_) import Control.Monad.Trans.Either import Control.Monad.Trans.Maybe--- import Data.Attoparsec-import Data.Attoparsec.Char8+import Data.Attoparsec.ByteString.Char8 import qualified Data.ByteString.Char8 as B import Data.Foldable (mapM_, forM_) import Data.List (sortBy)-import qualified Data.Map as M-import Data.Maybe (catMaybes)+import qualified Data.HashMap.Strict as M import Data.Monoid ((<>)) import qualified Data.Text as T import qualified Data.Text.Encoding as TE@@ -37,12 +36,14 @@ import Data.UUID.V4 (nextRandom) import qualified Graphics.Rendering.Cairo as Cairo import qualified Graphics.Rendering.Cairo.SVG as RSVG--- import qualified Graphics.Rendering.Pango.Cairo as Pango import qualified Graphics.UI.Gtk as Gtk import System.Directory import System.Exit (ExitCode(..)) import System.FilePath import System.Process (readProcessWithExitCode)+#ifdef HUB+import Control.Concurrent (killThread)+#endif -- import Control.Monad.Trans.Crtn import Control.Monad.Trans.Crtn.Event @@ -61,8 +62,9 @@ import Hoodle.Coroutine.Commit import Hoodle.Coroutine.Dialog import Hoodle.Coroutine.Draw +import Hoodle.Coroutine.LaTeX import Hoodle.Coroutine.Mode-import Hoodle.Coroutine.Network+import Hoodle.Coroutine.Page import Hoodle.Coroutine.Select.Clipboard import Hoodle.ModelAction.Layer import Hoodle.ModelAction.Page@@ -76,44 +78,24 @@ import Hoodle.Type.HoodleState import Hoodle.Type.PageArrangement import Hoodle.Util+#ifdef HUB+import Hoodle.Coroutine.Network+#endif -- import Prelude hiding (readFile,mapM_) --- | single line text input : almost abandoned now-textInputDialog :: MainCoroutine (Maybe String) -textInputDialog = do - doIOaction $ \_evhandler -> do - dialog <- Gtk.messageDialogNew Nothing [Gtk.DialogModal]- Gtk.MessageQuestion Gtk.ButtonsOkCancel "text input"- vbox <- Gtk.dialogGetUpper dialog- txtvw <- Gtk.textViewNew- Gtk.boxPackStart vbox txtvw Gtk.PackGrow 0 - Gtk.widgetShowAll dialog- res <- Gtk.dialogRun dialog - case res of - Gtk.ResponseOk -> do - buf <- Gtk.textViewGetBuffer txtvw - (istart,iend) <- (,) <$> Gtk.textBufferGetStartIter buf- <*> Gtk.textBufferGetEndIter buf- l <- Gtk.textBufferGetText buf istart iend True- Gtk.widgetDestroy dialog- return (UsrEv (TextInput (Just l)))- _ -> do - Gtk.widgetDestroy dialog- return (UsrEv (TextInput Nothing))- let go = do r <- nextevent- case r of - TextInput input -> return input - UpdateCanvas cid -> invalidateInBBox Nothing Efficient cid >> go - _ -> go - go - -- | common dialog with multiline edit input box -multiLineDialog :: T.Text -> Either (ActionOrder AllEvent) AllEvent-multiLineDialog str = mkIOaction $ \evhandler -> do+multiLineDialog :: T.Text -> (AllEvent -> IO ()) -> IO AllEvent+multiLineDialog str evhandler = do dialog <- Gtk.dialogNew+#ifdef GTK3 + upper <- fmap Gtk.castToContainer (Gtk.dialogGetContentArea dialog)+ vbox <- Gtk.vBoxNew False 0+ Gtk.containerAdd upper vbox+#else vbox <- Gtk.dialogGetUpper dialog+#endif textbuf <- Gtk.textBufferNew Nothing Gtk.textBufferSetByteString textbuf (TE.encodeUtf8 str) textbuf `Gtk.on` Gtk.bufferChanged $ do @@ -125,7 +107,7 @@ hscrbar <- Gtk.hScrollbarNew =<< Gtk.textViewGetHadjustment textarea textarea `Gtk.on` Gtk.sizeRequest $ return (Gtk.Requisition 500 600) fdesc <- Gtk.fontDescriptionNew- Gtk.fontDescriptionSetFamily fdesc "Mono"+ Gtk.fontDescriptionSetFamily fdesc ("Mono" :: String) Gtk.widgetModifyFont textarea (Just fdesc) -- table <- Gtk.tableNew 2 2 False@@ -134,16 +116,20 @@ Gtk.tableAttachDefaults table hscrbar 0 1 1 2 Gtk.boxPackStart vbox table Gtk.PackNatural 0 -- - _btnOk <- Gtk.dialogAddButton dialog "Ok" Gtk.ResponseOk- _btnCancel <- Gtk.dialogAddButton dialog "Cancel" Gtk.ResponseCancel- _btnNetwork <- Gtk.dialogAddButton dialog "Network" (Gtk.ResponseUser 1)+ _btnOk <- Gtk.dialogAddButton dialog ("Ok" :: String) Gtk.ResponseOk+ _btnCancel <- Gtk.dialogAddButton dialog ("Cancel" :: String) Gtk.ResponseCancel+#ifdef HUB+ _btnNetwork <- Gtk.dialogAddButton dialog ("Network" :: String) (Gtk.ResponseUser 1)+#endif Gtk.widgetShowAll dialog res <- Gtk.dialogRun dialog Gtk.widgetDestroy dialog case res of Gtk.ResponseOk -> return (UsrEv (OkCancel True)) Gtk.ResponseCancel -> return (UsrEv (OkCancel False))+#ifdef HUB Gtk.ResponseUser 1 -> return (UsrEv (NetworkProcess NetworkDialog))+#endif _ -> return (UsrEv (OkCancel False)) -- | main event loop for multiline edit box@@ -155,7 +141,9 @@ >> multiLineLoop txt OkCancel True -> (return . Just) txt OkCancel False -> return Nothing+#ifdef HUB NetworkProcess NetworkDialog -> networkTextInput txt+#endif MultiLine (MultiLineChanged txt') -> multiLineLoop txt' _ -> multiLineLoop txt @@ -164,21 +152,21 @@ textInput mpos str = do case mpos of Just (x0,y0) -> do - modify (tempQueue %~ enqueue (multiLineDialog str)) + doIOaction (multiLineDialog str) multiLineLoop str >>= mapM_ (\result -> deleteSelection >> liftIO (makePangoTextSVG (x0,y0) result) >>= svgInsert (result,"pango"))- Nothing -> liftIO $ putStrLn "textInput: not implemented"+ Nothing -> msgShout "textInput: not implemented" -- | insert latex laTeXInput :: Maybe (Double,Double) -> T.Text -> MainCoroutine () laTeXInput mpos str = do case mpos of Just (x0,y0) -> do - modify (tempQueue %~ enqueue (multiLineDialog str)) + doIOaction (multiLineDialog str) multiLineLoop str >>= - mapM_ (\result -> liftIO (makeLaTeXSVG (x0,y0) result) >>= \case + mapM_ (\result -> liftIO (makeLaTeXSVG (x0,y0) Nothing result) >>= \case Right r -> deleteSelection >> svgInsert (result,"latex") r Left err -> okMessageBox err >> laTeXInput mpos result )@@ -216,12 +204,13 @@ -- | +#ifdef HUB laTeXInputNetwork :: Maybe (Double,Double) -> T.Text -> MainCoroutine () laTeXInputNetwork mpos str = case mpos of Just (x0,y0) -> do networkTextInput str >>=- mapM_ (\result -> liftIO (makeLaTeXSVG (x0,y0) result) + mapM_ (\result -> liftIO (makeLaTeXSVG (x0,y0) Nothing result) >>= \case Right r -> deleteSelection >> svgInsert (result,"latex") r Left err -> okMessageBox err >> laTeXInput mpos result )@@ -230,41 +219,38 @@ autoPosText >>= maybe (laTeXInputNetwork (Just (100,100)) str) (\y'->laTeXInputNetwork (Just (100,y')) str) -+#endif dbusNetworkInput :: T.Text -> MainCoroutine () dbusNetworkInput txt = do modeChange ToViewAppendMode mpos <- autoPosText let pos = maybe (100,100) (100,) mpos - rsvg <- liftIO (makeLaTeXSVG pos txt) + rsvg <- liftIO (makeLaTeXSVG pos Nothing txt) case rsvg of Right r -> deleteSelection >> svgInsert (txt,"latex") r Left err -> okMessageBox err >> laTeXInput (Just pos) txt -laTeXHeader :: T.Text-laTeXHeader = "\\documentclass{article}\n\- \\\pagestyle{empty}\n\- \\\begin{document}\n"- -laTeXFooter :: T.Text-laTeXFooter = "\\end{document}\n"+check :: String -> IO (ExitCode,String) -> EitherT String IO ()+check msg act = do+ er <- liftIO $ Control.Exception.try act+ case er of + Left (Control.Exception.SomeException excp) -> left (show excp)+ Right (ecode,str) -> case ecode of ExitSuccess -> right () ; _ -> left (msg ++ ":" ++ str) -makeLaTeXSVG :: (Double,Double) -> T.Text ++makeLaTeXSVG :: (Double,Double) -> Maybe Dimension -> T.Text -> IO (Either String (B.ByteString,BBox))-makeLaTeXSVG (x0,y0) txt = do+makeLaTeXSVG (x0,y0) mdim txt = do cdir <- getCurrentDirectory tdir <- getTemporaryDirectory tfilename <- show <$> nextRandom- setCurrentDirectory tdir- let check msg act = liftIO act >>= \(ecode,str) -> case ecode of ExitSuccess -> right () ; _ -> left (msg ++ ":" ++ str)- B.writeFile (tfilename <.> "tex") (TE.encodeUtf8 txt) r <- runEitherT $ do check "error during xelatex" $ do - (ecode,ostr,estr) <- readProcessWithExitCode "xelatex" [tfilename <.> "tex"] ""+ (ecode,ostr,estr) <- readProcessWithExitCode "xelatex" ["-shell-escape", tfilename <.> "tex"] "" return (ecode,ostr++estr) check "error during pdfcrop" $ do (ecode,ostr,estr) <- readProcessWithExitCode "pdfcrop" [tfilename <.> "pdf",tfilename ++ "_crop" <.> "pdf"] "" @@ -274,8 +260,13 @@ return (ecode,ostr++estr) bstr <- liftIO $ B.readFile (tfilename <.> "svg") rsvg <- liftIO $ RSVG.svgNewFromString (B.unpack bstr) - let (w,h) = RSVG.svgGetSize rsvg- return (bstr,BBox (x0,y0) (x0+fromIntegral w,y0+fromIntegral h)) + let ow, oh :: Int+ (ow,oh) = RSVG.svgGetSize rsvg+ ow', oh' :: Double+ (ow',oh') = (fromIntegral ow, fromIntegral oh)+ w, h :: Double+ (w,h) = maybe (ow',oh') (\(Dim w' _)->(w',oh'*w'/ow')) mdim + return (bstr,BBox (x0,y0) (x0+w,y0+h)) setCurrentDirectory cdir return r @@ -283,9 +274,11 @@ -- | svgInsert :: (T.Text,String) -> (B.ByteString,BBox) -> MainCoroutine () svgInsert (txt,cmd) (svgbstr,BBox (x0,y0) (x1,y1)) = do - xstate <- get - let pgnum = view (unboxLens currentPageNum) . view currentCanvasInfo $ xstate- hdl = getHoodle xstate + xst <- get + let uhdl = view (unitHoodles.currentUnit) xst+ cid = getCurrentCanvasId uhdl+ pgnum = view (unboxLens currentPageNum) . view currentCanvasInfo $ uhdl+ hdl = getHoodle uhdl currpage = getPageFromGHoodleMap pgnum hdl currlayer = getCurrentLayer currpage --@@ -298,15 +291,15 @@ let otheritems = view gitems currlayer let ntpg = makePageSelectMode currpage (otheritems :- (Hitted [newitem]) :- Empty) - cache = view renderCache xstate modeChange ToSelectMode - nxstate <- get - thdl <- case view hoodleModeState nxstate of- SelectState thdl' -> return thdl'- _ -> (lift . EitherT . return . Left . Other) "svgInsert"- nthdl <- liftIO $ updateTempHoodleSelectIO cache thdl ntpg pgnum - put (set hoodleModeState (SelectState nthdl) nxstate)+ updateUhdl $ \nuhdl -> do+ thdl <- case view hoodleModeState nuhdl of+ SelectState thdl' -> return thdl'+ _ -> (lift . EitherT . return . Left . Other) "svgInsert"+ nthdl <- updateTempHoodleSelectM cid thdl ntpg pgnum + return $ (hoodleModeState .~ SelectState nthdl) nuhdl commit_+ canvasZoomUpdateAll invalidateAll -- | @@ -336,8 +329,9 @@ -> (B.ByteString,BBox) -> MainCoroutine () linkInsert _typ (uuidbstr,fname) str (svgbstr,BBox (x0,y0) (x1,y1)) = do - xstate <- get - let pgnum = view (currentCanvasInfo . unboxLens currentPageNum) xstate + xst <- get + let uhdl = view (unitHoodles.currentUnit) xst + let pgnum = view (currentCanvasInfo . unboxLens currentPageNum) uhdl lnk = Link uuidbstr "simple" (B.pack fname) (Just (B.pack str)) Nothing svgbstr (x0,y0) (Dim (x1-x0) (y1-y0)) nlnk <- liftIO $ convertLinkFromSimpleToDocID lnk >>= maybe (return lnk) return@@ -389,31 +383,12 @@ -- | combine all LaTeX texts into a text file combineLaTeXText :: MainCoroutine () combineLaTeXText = do- hdl <- rHoodle2Hoodle . getHoodle <$> get - let mlatex_components = do - (pgnum,pg) <- (zip ([1..] :: [Int]) . view pages) hdl - l <- view layers pg- i <- view items l- case i of - ItemSVG svg -> - case svg_command svg of- Just "latex" -> do - let (_,y) = svg_pos svg - return ((pgnum,y,) <$> svg_text svg) - _ -> []- _ -> []- let cfunc :: (Ord a,Ord b,Ord c) => (a,b,c) -> (a,b,c) -> Ordering - cfunc x y | view _1 x > view _1 y = GT- | view _1 x < view _1 y = LT- | otherwise = if | view _2 x > view _2 y -> GT- | view _2 x < view _2 y -> LT- | otherwise -> EQ- let latex_components = catMaybes mlatex_components- sorted = sortBy cfunc latex_components - resulttxt = (B.intercalate "%%%%%%%%%%%%\n\n%%%%%%%%%%\n" . map (view _3)) sorted+ hdl <- rHoodle2Hoodle . getHoodle . view (unitHoodles.currentUnit) <$> get + let sorted = getLaTeXComponentsFromHdl hdl+ + resulttxt = (T.intercalate "%%%%%%%%%%%%\n\n%%%%%%%%%%\n" . map (view (_2._3))) sorted mfilename <- fileChooser Gtk.FileChooserActionSave Nothing- forM_ mfilename (\filename -> liftIO (B.writeFile filename resulttxt) >> return ())-+ forM_ mfilename (\filename -> liftIO (TIO.writeFile filename resulttxt) >> return ()) insertItemAt :: Maybe (PageNum,PageCoordinate) @@ -421,11 +396,13 @@ -> MainCoroutine () insertItemAt mpcoord ritm = do xst <- get - geometry <- liftIO (getGeometry4CurrCvs xst) - let hdl = getHoodle xst + let uhdl = view (unitHoodles.currentUnit) xst+ geometry <- liftIO (getGeometry4CurrCvs uhdl) + let cid = getCurrentCanvasId uhdl+ hdl = getHoodle uhdl (pgnum,mpos) = case mpcoord of Just (PageNum n,pos) -> (n,Just pos)- Nothing -> (view (currentCanvasInfo . unboxLens currentPageNum) xst,Nothing)+ Nothing -> (view (currentCanvasInfo . unboxLens currentPageNum) uhdl,Nothing) (ulx,uly) = (bbox_upperleft.getBBox) ritm nitms = case mpos of @@ -438,14 +415,15 @@ oitms = view gitems lyr ntpg = makePageSelectMode pg (oitms :- (Hitted nitms) :- Empty) modeChange ToSelectMode - nxst <- get - let cache = view renderCache nxst- thdl <- case view hoodleModeState nxst of- SelectState thdl' -> return thdl'- _ -> (lift . EitherT . return . Left . Other) "insertItemAt"- nthdl <- liftIO $ updateTempHoodleSelectIO cache thdl ntpg pgnum - put ( ( set hoodleModeState (SelectState nthdl) - . set isOneTimeSelectMode YesAfterSelect) nxst)+ updateUhdl $ \uhdl' -> do + thdl <- case view hoodleModeState uhdl' of+ SelectState thdl' -> return thdl'+ _ -> (lift . EitherT . return . Left . Other) "insertItemAt"+ nthdl <- updateTempHoodleSelectM cid thdl ntpg pgnum + return . (hoodleModeState .~ SelectState nthdl)+ . (isOneTimeSelectMode .~ YesAfterSelect) $ uhdl' + commit_+ canvasZoomUpdateAll invalidateAll embedTextSource :: MainCoroutine ()@@ -453,53 +431,59 @@ mfilename <- fileChooser Gtk.FileChooserActionOpen Nothing forM_ mfilename $ \filename -> do txt <- liftIO $ TIO.readFile filename- xst <- get- let nhdlmodst = case xst ^. hoodleModeState of- ViewAppendState hdl -> (ViewAppendState . (gembeddedtext .~ Just txt) $ hdl)- SelectState thdl -> (SelectState . (gselEmbeddedText .~ Just txt) $ thdl)- nxst = (hoodleModeState .~ nhdlmodst) xst- put nxst+ pureUpdateUhdl $ \uhdl ->+ let nhdlmodst = case uhdl ^. hoodleModeState of+ ViewAppendState hdl -> (ViewAppendState . (gembeddedtext .~ Just txt) $ hdl)+ SelectState thdl -> (SelectState . (gselEmbeddedText .~ Just txt) $ thdl)+ in (hoodleModeState .~ nhdlmodst) uhdl commit_ -- | editEmbeddedTextSource :: MainCoroutine () editEmbeddedTextSource = do - hdl <- getHoodle <$> get+ hdl <- getHoodle . view (unitHoodles.currentUnit) <$> get let mtxt = hdl ^. gembeddedtext forM_ mtxt $ \txt -> do - modify (tempQueue %~ enqueue (multiLineDialog txt)) + doIOaction (multiLineDialog txt) multiLineLoop txt >>= \case Nothing -> return () Just ntxt -> do - modify $ \xst ->- let nhdlmodst = case xst ^. hoodleModeState of- ViewAppendState hdl -> (ViewAppendState . (gembeddedtext .~ Just ntxt) $ hdl)+ pureUpdateUhdl $ \uhdl ->+ let nhdlmodst = case uhdl ^. hoodleModeState of+ ViewAppendState hdl' -> (ViewAppendState . (gembeddedtext .~ Just ntxt) $ hdl') SelectState thdl -> (SelectState . (gselEmbeddedText .~ Just ntxt) $ thdl)- in (hoodleModeState .~ nhdlmodst) xst+ in (hoodleModeState .~ nhdlmodst) uhdl commit_ + -- |+#ifdef HUB editNetEmbeddedTextSource :: MainCoroutine () editNetEmbeddedTextSource = do - hdl <- getHoodle <$> get+ hdl <- getHoodle . view (unitHoodles.currentUnit) <$> get let mtxt = hdl ^. gembeddedtext forM_ mtxt $ \txt -> do - -- modify (tempQueue %~ enqueue (multiLineDialog txt)) networkTextInput txt >>= \case Nothing -> return ()- Just ntxt -> do - modify $ \xst ->- let nhdlmodst = case xst ^. hoodleModeState of- ViewAppendState hdl -> (ViewAppendState . (gembeddedtext .~ Just ntxt) $ hdl)- SelectState thdl -> (SelectState . (gselEmbeddedText .~ Just ntxt) $ thdl)- in (hoodleModeState .~ nhdlmodst) xst- commit_+ Just ntxt -> networkReceived ntxt+#endif +#ifdef HUB+networkReceived :: T.Text -> MainCoroutine ()+networkReceived txt = do+ pureUpdateUhdl $ \uhdl -> + let nhdlmodst = case uhdl ^. hoodleModeState of+ ViewAppendState hdl -> (ViewAppendState . (gembeddedtext .~ Just txt) $ hdl)+ SelectState thdl -> (SelectState . (gselEmbeddedText .~ Just txt) $ thdl)+ in (hoodleModeState .~ nhdlmodst) uhdl+ commit_+#endif+ -- | insert text textInputFromSource :: (Double,Double) -> MainCoroutine () textInputFromSource (x0,y0) = do runMaybeT $ do - txtsrc <- MaybeT $ (^. gembeddedtext) . getHoodle <$> get+ txtsrc <- MaybeT $ (^. gembeddedtext) . getHoodle . view (unitHoodles.currentUnit) <$> get lift $ modify (tempQueue %~ enqueue linePosDialog) (l1,l2) <- MaybeT linePosLoop let txt = getLinesFromText (l1,l2) txtsrc@@ -510,23 +494,29 @@ -- | common dialog with line position linePosDialog :: Either (ActionOrder AllEvent) AllEvent-linePosDialog = mkIOaction $ \evhandler -> do+linePosDialog = mkIOaction $ \_evhandler -> do dialog <- Gtk.dialogNew+#ifdef GTK3+ upper <- fmap Gtk.castToContainer (Gtk.dialogGetContentArea dialog)+ vbox <- Gtk.vBoxNew False 0 + Gtk.containerAdd upper vbox+#else vbox <- Gtk.dialogGetUpper dialog+#endif hbox <- Gtk.hBoxNew False 0 Gtk.boxPackStart vbox hbox Gtk.PackNatural 0 - line1buf <- Gtk.entryBufferNew Nothing+ line1buf <- Gtk.entryBufferNew (Nothing :: Maybe String) line1 <- Gtk.entryNewWithBuffer line1buf Gtk.boxPackStart hbox line1 Gtk.PackNatural 2 - line2buf <- Gtk.entryBufferNew Nothing+ line2buf <- Gtk.entryBufferNew (Nothing :: Maybe String) line2 <- Gtk.entryNewWithBuffer line2buf Gtk.boxPackStart hbox line2 Gtk.PackNatural 2 -- - _btnOk <- Gtk.dialogAddButton dialog "Ok" Gtk.ResponseOk- _btnCancel <- Gtk.dialogAddButton dialog "Cancel" Gtk.ResponseCancel+ _btnOk <- Gtk.dialogAddButton dialog ("Ok" :: String) Gtk.ResponseOk+ _btnCancel <- Gtk.dialogAddButton dialog ("Cancel" :: String) Gtk.ResponseCancel Gtk.widgetShowAll dialog res <- Gtk.dialogRun dialog Gtk.widgetDestroy dialog@@ -551,57 +541,59 @@ _ -> linePosLoop -- | insert text -laTeXInputKeyword :: (Double,Double) -> T.Text -> MaybeT MainCoroutine ()-laTeXInputKeyword (x0,y0) keyword = do- txtsrc <- MaybeT $ (^. gembeddedtext) . getHoodle <$> get+laTeXInputKeyword :: (Double,Double) -> Maybe Dimension -> T.Text + -> MaybeT MainCoroutine ()+laTeXInputKeyword (x0,y0) mdim keyword = do+ txtsrc <- MaybeT $ (^. gembeddedtext) . getHoodle . view (unitHoodles.currentUnit) <$> get subpart <- (MaybeT . return . M.lookup keyword . getKeywordMap) txtsrc let subpart' = laTeXHeader <> "\n" <> subpart <> laTeXFooter- liftIO (makeLaTeXSVG (x0,y0) subpart') >>= \case+ liftIO (makeLaTeXSVG (x0,y0) mdim subpart') >>= \case Right r -> lift $ do deleteSelection svgInsert ("embedlatex:keyword:"<>keyword,"latex") r Left err -> lift $ do- okMessageBox err+ longTextMessageBox err+ -- okMessageBox err return () --- | insert text +-- | laTeXInputFromSource :: (Double,Double) -> MainCoroutine () laTeXInputFromSource (x0,y0) = do runMaybeT $ do - txtsrc <- MaybeT $ (^. gembeddedtext) . getHoodle <$> get- lift $ modify (tempQueue %~ enqueue keywordDialog) - keyword <- MaybeT keywordLoop- laTeXInputKeyword (x0,y0) keyword+ txtsrc <- MaybeT $ (^. gembeddedtext) . getHoodle . view (unitHoodles.currentUnit) <$> get+ let keylst = (map fst . M.toList . getKeywordMap) txtsrc+ when ((not.null) keylst) $ do + keyword <- MaybeT (keywordDialog keylst)+ laTeXInputKeyword (x0,y0) Nothing keyword return ()---- | common dialog with line position -keywordDialog :: Either (ActionOrder AllEvent) AllEvent-keywordDialog = mkIOaction $ \evhandler -> do- dialog <- Gtk.dialogNew- vbox <- Gtk.dialogGetUpper dialog- hbox <- Gtk.hBoxNew False 0- Gtk.boxPackStart vbox hbox Gtk.PackNatural 0- keybuf <- Gtk.entryBufferNew Nothing- key <- Gtk.entryNewWithBuffer keybuf- Gtk.boxPackStart hbox key Gtk.PackNatural 2- -- - _btnOk <- Gtk.dialogAddButton dialog "Ok" Gtk.ResponseOk- _btnCancel <- Gtk.dialogAddButton dialog "Cancel" Gtk.ResponseCancel- Gtk.widgetShowAll dialog- res <- Gtk.dialogRun dialog- Gtk.widgetDestroy dialog- case res of - Gtk.ResponseOk -> do- keystr <- T.pack <$> Gtk.get keybuf Gtk.entryBufferText- (return . UsrEv . Keyword . Just) keystr- Gtk.ResponseCancel -> return (UsrEv (Keyword Nothing))- _ -> return (UsrEv (Keyword Nothing))+ +-- | +#ifdef HUB+toggleNetworkEditSource :: MainCoroutine ()+toggleNetworkEditSource = do + xst <- get+ let uhdl = view (unitHoodles.currentUnit) xst+ hdl = getHoodle uhdl+ mtxt = hdl ^. gembeddedtext+ b <- updateFlagFromToggleUI "TOGGLENETSRCA" (settings.doesUseXInput)+ forM_ (xst ^. statusBar) $ \stbar -> + if b + then do+ (ip,tid,_done) <- networkTextInputBody (maybe " " id mtxt)+ doIOaction_ $ do+ let msg = ("networkedit " ++ ip ++ " 4040")+ ctxt <- Gtk.statusbarGetContextId stbar ("networkedit" :: String)+ Gtk.statusbarPush stbar ctxt msg+ (put . ((settings.networkEditSourceInfo) .~ (Just tid))) xst+ else do+ case xst ^. (settings.networkEditSourceInfo) of+ Nothing -> return ()+ Just tid -> do+ doIOaction_ $ do+ killThread tid+ ctxt <- Gtk.statusbarGetContextId stbar ("networkedit" :: String)+ Gtk.statusbarPush stbar ctxt ("Now no networkedit" :: String)+ (put . ((settings.networkEditSourceInfo) .~ Nothing)) xst+#endif+ --- | main event loop for line position dialog-keywordLoop :: MainCoroutine (Maybe T.Text)-keywordLoop = do - r <- nextevent- case r of - UpdateCanvas cid -> invalidateInBBox Nothing Efficient cid >> keywordLoop- Keyword x -> return x- _ -> keywordLoop
src/Hoodle/Coroutine/VerticalSpace.hs view
@@ -1,9 +1,11 @@+{-# LANGUAGE CPP #-}+ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Coroutine.VerticalSpace--- Copyright : (c) 2013, 2014 Ian-Woo Kim+-- Copyright : (c) 2013-2015 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -14,7 +16,7 @@ import Control.Applicative import Control.Category-import Control.Lens (view,set,at)+import Control.Lens (view,set,at,(.~)) import Control.Monad hiding (mapM_) import Control.Monad.State (get) import Control.Monad.Trans (liftIO)@@ -22,16 +24,15 @@ import Data.Monoid import Data.Time.Clock import qualified Graphics.Rendering.Cairo as Cairo-import Graphics.UI.Gtk hiding (get,set) +import qualified Graphics.UI.Gtk as Gtk -- from hoodle-platform import Data.Hoodle.BBox import Data.Hoodle.Generic import Data.Hoodle.Simple (Dimension(..)) import Data.Hoodle.Zipper (SeqZipper,toSeq) import Graphics.Hoodle.Render+import Graphics.Hoodle.Render.Type import Graphics.Hoodle.Render.Type.HitTest-import Graphics.Hoodle.Render.Type.Hoodle-import Graphics.Hoodle.Render.Type.Item import Graphics.Hoodle.Render.Util.HitTest -- from this package import Hoodle.Accessor@@ -52,6 +53,7 @@ import Hoodle.Type.Predefined import Hoodle.View.Coordinate import Hoodle.View.Draw+import Hoodle.Util -- import Prelude hiding ((.), id, concat,concatMap,mapM_) @@ -73,12 +75,12 @@ bboxabove (BBox (_,y0) _) = y0 > y -- |-verticalSpaceStart :: CanvasId -> PointerCoord -> MainCoroutine () -verticalSpaceStart cid = commonPenStart verticalSpaceAction cid +verticalSpaceStart :: CanvasId -> PointerCoord -> MainCoroutine ()+verticalSpaceStart cid = commonPenStart verticalSpaceAction cid >=> const (return ()) where - verticalSpaceAction _cinfo pnum@(PageNum n) geometry (x,y) = do - hdl <- liftM getHoodle get - cache <- view renderCache <$> get+ verticalSpaceAction _cinfo pnum@(PageNum n) geometry (x,y) _ = do + hdl <- getHoodle . view (unitHoodles.currentUnit) <$> get + cache <- renderCache cpg <- getCurrentPageCurr let (itms,npg,hltedLayers) = splitPageByHLine y cpg nhdl = set (gpages.at n) (Just npg) hdl @@ -86,7 +88,7 @@ case mbbx of Nothing -> return () Just bbx -> do - (sfcbkg,Dim w h) <- liftIO $ canvasImageSurface cache Nothing geometry nhdl + (sfcbkg,Dim w h) <- liftIO $ canvasImageSurface cache cid Nothing geometry nhdl sfcitm <- liftIO $ Cairo.createImageSurface Cairo.FormatARGB32 (floor w) (floor h) sfctot <- liftIO $ Cairo.createImageSurface @@ -94,7 +96,7 @@ liftIO $ Cairo.renderWith sfcitm $ do Cairo.identityMatrix cairoXform4PageCoordinate (mkXform4Page geometry pnum)- mapM_ (renderRItem cache) itms+ mapM_ (renderRItem cache cid) itms ctime <- liftIO getCurrentTime verticalSpaceProcess cid geometry (bbx,hltedLayers,pnum,cpg) (x,y) (sfcbkg,sfcitm,sfctot) ctime @@ -103,31 +105,30 @@ -- | addNewPageAndMoveBelow :: (PageNum,SeqZipper RItemHitted,BBox) -> MainCoroutine () -addNewPageAndMoveBelow (pnum,hltedLyrs,bbx) = - updateXState npgBfrAct - >> commit_ - >> canvasZoomUpdateAll >> invalidateAll+addNewPageAndMoveBelow (pnum,hltedLyrs,bbx) = do+ bsty <- view backgroundStyle <$> get+ updateUhdl (npgact bsty) >> commit_ >> canvasZoomUpdateAll >> invalidateAll where- npgBfrAct xst = forBoth' unboxBiAct (fsimple xst) . view currentCanvasInfo $ xst- fsimple :: HoodleState -> CanvasInfo a -> MainCoroutine HoodleState- fsimple xstate _cinfo = do - case view hoodleModeState xstate of + npgact :: BackgroundStyle -> UnitHoodle -> MainCoroutine UnitHoodle+ npgact bsty uhdl = do + case view hoodleModeState uhdl of ViewAppendState hdl -> do - let bsty = view backgroundStyle xstate - hdl' <- addNewPageInHoodle bsty PageAfter hdl (unPageNum pnum)- let hdl'' = moveBelowToNewPage (pnum,hltedLyrs,bbx) hdl' - nhdlmodst = ViewAppendState hdl''- return =<< liftIO . updatePageAll nhdlmodst- . set hoodleModeState nhdlmodst $ xstate + hdl' <- addNewPageInHoodle Nothing bsty PageAfter hdl (unPageNum pnum)+ sfcid <- issueSurfaceID+ sfcid2 <- issueSurfaceID+ let nhdlmodst = ViewAppendState (moveBelowToNewPage (sfcid,sfcid2) (pnum,hltedLyrs,bbx) hdl') + liftIO . updatePageAll nhdlmodst . (hoodleModeState .~ nhdlmodst) $ uhdl SelectState _ -> do - liftIO $ putStrLn " not implemented yet"- return xstate+ msgShout "addNewPageAndMoveBelow: not implemented yet"+ return uhdl -- | -moveBelowToNewPage :: (PageNum,SeqZipper RItemHitted,BBox) - -> Hoodle EditMode- -> Hoodle EditMode-moveBelowToNewPage (PageNum n,hltedLayers,BBox (_,y0) _) hdl = +moveBelowToNewPage :: (SurfaceID,SurfaceID) + -- ^ sfcid: old page, sfcid2: new page+ -> (PageNum,SeqZipper RItemHitted,BBox) + -> Hoodle EditMode+ -> Hoodle EditMode+moveBelowToNewPage (sfcid,sfcid2) (PageNum n,hltedLayers,BBox (_,y0) _) hdl = let mpg = view (gpages.at n) hdl mpg2 = view (gpages.at (n+1)) hdl in case (,) <$> mpg <*> mpg2 of @@ -137,15 +138,14 @@ fmap (fmapAL id (fmap (changeItemBy (\(x',y')->(x',y'+10-y0))))) hltedLayers- nlyrs = fmap ((\x -> set gitems x emptyRLayer) + nlyrs = fmap ((\x -> set gitems x (emptyRLayer sfcid)) . concatMap unNotHitted . getA ) nhlyrs npg = set glayers nlyrs pg - nnlyrs = fmap ((\x -> set gitems x emptyRLayer)+ nnlyrs = fmap ((\x -> set gitems x (emptyRLayer sfcid2)) . concatMap unHitted . getB ) nhlyrs npg2 = set glayers nnlyrs pg2- nhdl = ( set (gpages.at (n+1)) (Just npg2) . set (gpages.at n) (Just npg) ) hdl in nhdl @@ -163,18 +163,15 @@ verticalSpaceProcess cid geometry pinfo@(bbx,hltedLayers,pnum@(PageNum n),pg) (x0,y0) sfcs@(sfcbkg,sfcitm,sfctot) otime = do r <- nextevent - xst <- get- forBoth' unboxBiAct (f r xst) . getCanvasInfo cid $ xst + uhdl <- view (unitHoodles.currentUnit) <$> get+ forBoth' unboxBiAct (f r) . getCanvasInfo cid $ uhdl where Dim w h = view gdimension pg CvsCoord (_,y0_cvs) = (desktop2Canvas geometry . page2Desktop geometry) (pnum,PageCoord (x0,y0)) -------------------------------------------------------------- f :: UserEvent -> HoodleState -> CanvasInfo a -> MainCoroutine ()- f r xstate cvsInfo = penMoveAndUpOnly r pnum geometry defact - (moveact xstate cvsInfo) upact- ------------------------------------------------------------- + f :: UserEvent -> CanvasInfo a -> MainCoroutine ()+ f r cvsInfo = penMoveAndUpOnly r pnum geometry defact (moveact cvsInfo) upact defact = verticalSpaceProcess cid geometry pinfo (x0,y0) sfcs otime- ------------------------------------------------------------- upact pcoord = do let mpgcoord = (desktop2Page geometry . device2Desktop geometry) pcoord case mpgcoord of @@ -187,25 +184,24 @@ let BBox _ (_,by1) = bbx if by1 + y - y0 < h then do - xst <- get - let hdl = getHoodle xst - let nhlyrs = - fmap (fmapAL id - (fmap (changeItemBy (\(x',y')->(x',y'+y-y0)))))- hltedLayers- nlyrs = fmap - ((\is -> set gitems is emptyRLayer) - . concat- . interleave unNotHitted unHitted) - nhlyrs - npg = set glayers nlyrs pg - nhdl = set (gpages.at n) (Just npg) hdl - commit (set hoodleModeState (ViewAppendState nhdl) xst)+ sfcid <- issueSurfaceID+ pureUpdateUhdl $ \uhdl -> do+ let hdl = getHoodle uhdl+ nhlyrs = fmap (fmapAL id (fmap (changeItemBy (\(x',y')->(x',y'+y-y0))))) hltedLayers+ nlyrs = fmap ( (\is -> set gitems is (emptyRLayer sfcid)) + . concat . interleave unNotHitted unHitted ) + nhlyrs + npg = set glayers nlyrs pg + nhdl = set (gpages.at n) (Just npg) hdl + nhdlmodst = ViewAppendState nhdl+ nuhdl = (hoodleModeState .~ nhdlmodst) uhdl+ in nuhdl+ commit_+ canvasZoomUpdateAll invalidateAll - else do - addNewPageAndMoveBelow (pnum,hltedLayers,bbx)+ else addNewPageAndMoveBelow (pnum,hltedLayers,bbx) -------------------------------------------------------------- moveact _xstate cvsInfo (_,(x,y)) = + moveact cvsInfo (_,(x,y)) = processWithDefTimeInterval (verticalSpaceProcess cid geometry pinfo (x0,y0) sfcs) (\ctime -> do @@ -247,8 +243,16 @@ Cairo.paint drawguide let canvas = view drawArea cvsInfo - win <- liftIO $ widgetGetDrawWindow canvas- liftIO $ renderWithDrawable win $ do +#ifdef GTK3+ Just win <- liftIO $ Gtk.widgetGetWindow canvas+#else + win <- liftIO $ Gtk.widgetGetDrawWindow canvas+#endif+#ifdef GTK3+ liftIO $ Gtk.renderWithDrawWindow win $ do +#else + liftIO $ Gtk.renderWithDrawable win $ do +#endif Cairo.setSourceSurface sfctot 0 0 Cairo.setOperator Cairo.OperatorSource Cairo.paint
src/Hoodle/Coroutine/Window.hs view
@@ -1,11 +1,13 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE ScopedTypeVariables #-} ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Coroutine.Window --- Copyright : (c) 2011-2014 Ian-Woo Kim+-- Copyright : (c) 2011-2015 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -14,16 +16,21 @@ module Hoodle.Coroutine.Window where -import Control.Lens (view,set,over)+import Control.Applicative+import Control.Lens (view,set,over,(^.),(.~),_2) import Control.Monad.State import qualified Data.IntMap as M-import Graphics.UI.Gtk hiding (get,set)+import qualified Data.List as L+import Data.UUID (UUID)+import qualified Graphics.UI.Gtk as Gtk -- import Data.Hoodle.Generic import Data.Hoodle.Simple (Dimension(..)) -- import Hoodle.Accessor import Hoodle.Coroutine.Draw+import Hoodle.Coroutine.File+import Hoodle.Coroutine.Mode import Hoodle.Coroutine.Page import Hoodle.GUI.Reflect import Hoodle.ModelAction.Page@@ -34,7 +41,9 @@ import Hoodle.Type.Event import Hoodle.Type.HoodleState import Hoodle.Type.PageArrangement+import Hoodle.Type.Undo import Hoodle.Type.Window+import Hoodle.Util -- -- | canvas configure with general zoom update func@@ -43,17 +52,15 @@ -> CanvasDimension -> MainCoroutine () canvasConfigureGenUpdate updatefunc cid cdim - = updateXState (unboxBiAct fsingle fcont . getCanvasInfo cid ) >> updatefunc - where fsingle cinfo = do - xstate <- get + = updateUhdl (\uhdl -> unboxBiAct (fsingle uhdl) (fcont uhdl) (getCanvasInfo cid uhdl)) >> updatefunc + where fsingle uhdl cinfo = do cinfo' <- liftIO $ updateCanvasDimForSingle cdim cinfo - return $ setCanvasInfo (cid,CanvasSinglePage cinfo') xstate- fcont cinfo = do - xstate <- get+ return $ setCanvasInfo (cid,CanvasSinglePage cinfo') uhdl+ fcont uhdl cinfo = do page <- getCurrentPageCvsId cid let pdim = PageDimension (view gdimension page) cinfo' <- liftIO $ updateCanvasDimForContSingle pdim cdim cinfo - return $ setCanvasInfo (cid,CanvasContPage cinfo') xstate + return $ setCanvasInfo (cid,CanvasContPage cinfo') uhdl -- | doCanvasConfigure :: CanvasId -> CanvasDimension -> MainCoroutine () @@ -62,42 +69,40 @@ -- | eitherSplit :: SplitType -> MainCoroutine () eitherSplit stype = do- xstate <- get- let cmap = getCanvasInfoMap xstate- currcid = getCurrentCanvasId xstate+ xst <- get+ let uhdl = view (unitHoodles.currentUnit) xst+ let cmap = view cvsInfoMap uhdl+ currcid = getCurrentCanvasId uhdl newcid = newCanvasId cmap - fstate = view frameState xstate+ fstate = view frameState uhdl enewfstate = splitWindow currcid (newcid,stype) fstate case enewfstate of Left _ -> return () Right fstate' -> do cinfobox <- maybeError "eitherSplit" . M.lookup currcid $ cmap - let rtwin = view rootWindow xstate- rtcntr = view rootContainer xstate - rtrwin = view rootOfRootWindow xstate - liftIO $ containerRemove rtcntr rtwin- (xstate'',win,fstate'') <- - liftIO $ constructFrame' cinfobox xstate fstate'- let xstate3 = set frameState fstate'' - . set rootWindow win - $ xstate''- put xstate3 - liftIO $ boxPackEnd rtcntr win PackGrow 0 - liftIO $ widgetShowAll rtcntr - liftIO $ widgetQueueDraw rtrwin- (xstate4,_wconf) <- liftIO $ eventConnect xstate3 (view frameState xstate3)- xstate5 <- liftIO $ updatePageAll (view hoodleModeState xstate4) xstate4- put xstate5 + let callback = view callBack xst+ rtwin = view rootWindow uhdl+ rtcntr = view rootContainer uhdl+ rtrwin = view rootOfRootWindow xst + liftIO $ Gtk.containerRemove rtcntr rtwin+ (uhdl',win,fstate'') <- liftIO $ constructFrame' callback cinfobox uhdl fstate'+ let uhdl'' = ((frameState .~ fstate'') . (rootWindow .~ win)) uhdl'+ let xst3 = (unitHoodles.currentUnit .~ uhdl'') xst+ put xst3 + liftIO $ registerFrameToContainer rtrwin rtcntr win+ (uhdl3,_wconf) <- liftIO $ eventConnect xst3 uhdl'' (view frameState uhdl'')+ updateUhdl $ const (liftIO $ updatePageAll (view hoodleModeState uhdl3) uhdl3) canvasZoomUpdateAll invalidateAll -- | deleteCanvas :: MainCoroutine () deleteCanvas = do - xstate <- get- let cmap = getCanvasInfoMap xstate- currcid = getCurrentCanvasId xstate- fstate = view frameState xstate+ xst <- get+ let uhdl = view (unitHoodles.currentUnit) xst+ cmap = view cvsInfoMap uhdl+ currcid = getCurrentCanvasId uhdl+ fstate = view frameState uhdl enewfstate = removeWindow currcid fstate case enewfstate of Left _ -> return ()@@ -105,25 +110,23 @@ Right (Just fstate') -> do let cmap' = M.delete currcid cmap newcurrcid = maximum (M.keys cmap')- xstate0 <- changeCurrentCanvasId newcurrcid - let xstate1 = maybe xstate0 id $ setCanvasInfoMap cmap' xstate0- put xstate1- let rtwin = view rootWindow xstate1- rtcntr = view rootContainer xstate1 - rtrwin = view rootOfRootWindow xstate1 - liftIO $ containerRemove rtcntr rtwin- (xstate'',win,fstate'') <- liftIO $ constructFrame xstate1 fstate'- let xstate3 = set frameState fstate'' - . set rootWindow win - $ xstate''- put xstate3- liftIO $ boxPackEnd rtcntr win PackGrow 0 - liftIO $ widgetShowAll rtcntr - liftIO $ widgetQueueDraw rtrwin- (xstate4,_wconf) <- liftIO $ eventConnect xstate3 (view frameState xstate3)+ updateUhdl $ \_uhdl -> do+ uhdl' <- changeCurrentCanvasId newcurrcid + maybe (return uhdl') return $ setCanvasInfoMap cmap' uhdl'+ xst1 <- get+ let uhdl1 = view (unitHoodles.currentUnit) xst1+ let rtwin = view rootWindow uhdl1+ rtcntr = view rootContainer uhdl1 + rtrwin = view rootOfRootWindow xst1 + liftIO $ Gtk.containerRemove rtcntr rtwin+ (uhdl2,win,fstate'') <- liftIO $ constructFrame xst1 uhdl1 fstate'+ pureUpdateUhdl (const (((frameState .~ fstate'') . (rootWindow .~ win)) uhdl2))+ xst3 <- get+ liftIO $ registerFrameToContainer rtrwin rtcntr win+ updateUhdl $ \uhdl' -> do+ (uhdl'',_wconf) <- liftIO $ eventConnect xst3 uhdl' (view frameState uhdl')+ liftIO $ updatePageAll (view hoodleModeState uhdl'') uhdl'' canvasZoomUpdateAll- xstate5 <- liftIO $ updatePageAll (view hoodleModeState xstate4) xstate4- put xstate5 invalidateAll @@ -133,35 +136,116 @@ ev <- nextevent case ev of UpdateCanvas cid -> invalidateInBBox Nothing Efficient cid >> paneMoveStart - PaneMoveEnd -> do - return () - CanvasConfigure cid w' h'-> do - canvasConfigureGenUpdate canvasZoomUpdateBufAll cid (CanvasDimension (Dim w' h')) - >> paneMoveStart+ PaneMoveEnd -> return () + CanvasConfigure cid w' h'->+ canvasConfigureGenUpdate canvasZoomUpdateBufAll cid (CanvasDimension (Dim w' h')) >> paneMoveStart _ -> paneMoveStart - -- | not yet implemented? paneMoved :: MainCoroutine () -paneMoved = do - liftIO $ putStrLn "pane moved called"+paneMoved = msgShout "paneMoved: not implemented" --- |+-- | start full screen mode fullScreen :: MainCoroutine () fullScreen = do xst <- get - let b = view isFullScreen xst- rwin = view rootOfRootWindow xst - if b - then do - liftIO $ windowUnfullscreen rwin- modify (over isFullScreen (const False))- else do - liftIO $ windowFullscreen rwin - modify (over isFullScreen (const True))+ let rwin = view rootOfRootWindow xst + if view isFullScreen xst + then liftIO (Gtk.windowUnfullscreen rwin) >> modify (over isFullScreen (const False))+ else liftIO (Gtk.windowFullscreen rwin) >> modify (over isFullScreen (const True)) - - - - +-- |+addTab :: FileStore -> MainCoroutine ()+addTab filestore = do+ xst <- get+ let notebook = xst ^. rootNotebook+ callback = xst ^. callBack+ btnold = xst ^. (unitHoodles.currentUnit.unitButton)+ liftIO $ Gtk.widgetSetSensitive btnold False+ vboxcvs <- liftIO $ Gtk.vBoxNew False 0+ (tabnum,uuid,btn) <- liftIO $ createTab callback notebook vboxcvs+ let wconf = Node 1+ initcvs = defaultCvsInfoSinglePage { _canvasId = 1 }+ initcvsbox = CanvasSinglePage initcvs+ -- mfp = fileStore2Maybe filestore+ uhdl' <- (undoTable .~ emptyUndo 50) -- (undo = 50 for the time being) + . (frameState .~ wconf) + . updateFromCanvasInfoAsCurrentCanvas initcvsbox+ . (cvsInfoMap .~ M.empty)+ . (isSaved .~ True)+ . (hoodleFileControl.hoodleFileName .~ filestore) + . (unitKey .~ tabnum) + . (unitUUID .~ uuid) + . (unitButton .~ btn)+ <$> liftIO emptyUnitHoodle+ modify . set (unitHoodles.currentUnit) =<< (liftIO $ do+ (uhdl'',wdgt,_) <- constructFrame xst uhdl' wconf+ let uhdl3 = (rootWindow .~ wdgt) . (rootContainer .~ Gtk.castToBox vboxcvs) $ uhdl''+ (uhdl4,_wconf) <- eventConnect xst uhdl3 (view frameState uhdl3)+ registerFrameToContainer (xst^.rootOfRootWindow) (Gtk.castToBox vboxcvs) wdgt+ Gtk.widgetShowAll notebook+ return uhdl4) + doIOaction_ $ + blockWhile (view (uiComponentSignalHandler.switchTabSignal) xst) $+ Gtk.set notebook [Gtk.notebookPage Gtk.:= tabnum]+ getFileContent filestore+ updateUhdl $ \uhdl -> do+ liftIO (updatePageAll (view hoodleModeState uhdl) uhdl)+ unboxBiAct (sing2ContPage uhdl) (const (return uhdl)) . view currentCanvasInfo $ uhdl+ pageZoomChange FitWidth+ canvasZoomUpdateAll+ invalidateAll + reflectCursor True++-- | +findTab :: UUID -> MainCoroutine (Maybe Int)+findTab uuid = do+ uhdlmap <- view (unitHoodles._2) <$> get+ let assoc = (map (\x -> (view unitUUID x,view unitKey x)) . M.elems) uhdlmap+ return (L.lookup uuid assoc)++-- |+switchTab :: Int -> MainCoroutine ()+switchTab tabnum = do+ xst <- get+ let notebook = view rootNotebook xst+ doIOaction_ $ Gtk.set notebook [Gtk.notebookPage Gtk.:= tabnum ]+ uhdls <- view unitHoodles <$> get++ let current = fst uhdls+ when (tabnum /= current) $ do + let uhdl = fromJustError "switchTab" (M.lookup tabnum (snd uhdls))+ liftIO $ Gtk.widgetSetSensitive (uhdls^.(currentUnit.unitButton)) False+ liftIO $ Gtk.widgetSetSensitive (uhdl^.unitButton) True+ modify $ (unitHoodles.currentUnit .~ uhdl)+ updateUhdl $ \uhdl' -> liftIO (updatePageAll (view hoodleModeState uhdl') uhdl')+#ifndef GTK3+ view currentCanvasInfo uhdl # + forBoth' unboxBiAct $ \cinfo -> do+ (w,h) <- liftIO $ Gtk.widgetGetSize (cinfo^.drawArea) + doCanvasConfigure (cinfo^.canvasId) (CanvasDimension (Dim (fromIntegral w) (fromIntegral h)))+#endif+ invalidateAll + liftIO $ reflectUIToggle (xst ^. gtkUIManager) "SAVEA" (not (uhdl ^. isSaved))+ reflectPenModeUI+ reflectCursor True++-- |+closeTab :: MainCoroutine ()+closeTab = do + xst <- get+ let (currk,uhdlmap) = xst ^. unitHoodles+ uhdlmap' = M.delete currk uhdlmap + uhdllst'' = (map (\(x,y)-> (x,(unitKey .~ x) y)) . zip [0..] . M.elems) uhdlmap'+ uhdlmap'' = M.fromList uhdllst''+ sz = M.size uhdlmap+ if (sz > 1) + then do+ let notebook = xst ^. rootNotebook+ doIOaction_ $ Gtk.notebookRemovePage notebook currk+ modify $ (unitHoodles .~ (0,uhdlmap''))+ canvasZoomUpdateAll+ switchTab 0+ else liftIO $ Gtk.mainQuit+
src/Hoodle/Device.hsc view
@@ -1,9 +1,11 @@-{-# LANGUAGE ForeignFunctionInterface, ScopedTypeVariables #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE ScopedTypeVariables #-} ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Device --- Copyright : (c) 2011-2013 Ian-Woo Kim+-- Copyright : (c) 2011-2014 Ian-Woo Kim -- -- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>@@ -72,12 +74,11 @@ -> CString -- ^ touch -> IO () -+{- -- | foreign import ccall "c_initdevice.h find_wacom" c_find_wacom :: CString -> CString -> IO ()--{- + -- | foreign import ccall "c_initdevice.h enable_touch" c_enable_touch :: CString -> IO ()@@ -97,9 +98,6 @@ ptouchname_detect <- newCString "touch" -- c_find_wacom pstylusname_detect perasername_detect (mcore,mstylus,meraser,mtouch) <- getPenDevConfig cfg - -- putStrLn $ show mstylus - -- putStrLn $ show meraser- -- putStrLn $ show mtouch with 0 $ \pcore -> with 0 $ \pstylus -> with 0 $ \peraser -> do @@ -217,7 +215,11 @@ -> (Double,Double) -> IO (Double,Double) wacomCoordConvert canvas (x,y)= do +#ifdef GTK3 + Just win <- widgetGetWindow canvas -- partial function for the time being +#else // GTK3 win <- widgetGetDrawWindow canvas+#endif // GTK3 (x0,y0) <- drawWindowGetOrigin win screen <- widgetGetScreen canvas (ws,hs) <- (,) <$> screenGetWidth screen <*> screenGetHeight screen
src/Hoodle/GUI.hs view
@@ -1,9 +1,11 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE Rank2Types #-} {-# LANGUAGE ScopedTypeVariables #-} ----------------------------------------------------------------------------- -- | -- Module : Hoodle.GUI --- Copyright : (c) 2011-2013 Ian-Woo Kim+-- Copyright : (c) 2011-2014 Ian-Woo Kim -- -- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>@@ -16,14 +18,14 @@ import Control.Concurrent (threadDelay, forkIO) import Control.Exception (SomeException(..),catch)-import Control.Lens (view)-import Control.Monad hiding (mapM_)+import Control.Lens+import Control.Monad hiding (mapM_,forM_) import Control.Monad.Trans -import Data.Foldable (mapM_)+import Data.Foldable (mapM_,forM_) import qualified Data.IntMap as M import Data.IORef import Data.Maybe-import Graphics.UI.Gtk hiding (get,set)+import qualified Graphics.UI.Gtk as Gtk import System.Directory import System.Environment import System.FilePath@@ -40,92 +42,99 @@ import Hoodle.Type.Event import Hoodle.Type.HoodleState ---import Prelude ((.),($),String,Bool(..),const,error,flip,id,map) +import Prelude ((.),($),String,Bool(..),error,flip,id,map) -- | startGUI :: Maybe FilePath -> Maybe Hook -> IO () startGUI mfname mhook = do - initGUI- window <- windowNew - windowSetDefaultSize window 800 400- cfg <- loadConfigFile - devlst <- initDevice cfg - maxundo <- getMaxUndo cfg >>= - \mmax -> maybe (return 50) (return . id) mmax- xinputbool <- getXInputConfig cfg - (usepz,uselyr) <- getWidgetConfig cfg - statusbar <- statusbarNew - (tref,st0,ui,vbox) <- initCoroutine devlst window mhook maxundo (xinputbool,usepz,uselyr) statusbar - setTitleFromFileName st0- -- need for refactoring- setToggleUIForFlag "UXINPUTA" (settings.doesUseXInput) st0 - setToggleUIForFlag "HANDA" (settings.doesUseTouch) st0 - setToggleUIForFlag "POPMENUA" (settings.doesUsePopUpMenu) st0 - setToggleUIForFlag "EBDIMGA" (settings.doesEmbedImage) st0 - setToggleUIForFlag "EBDPDFA" (settings.doesEmbedPDF) st0- -- - let canvases = map (getDrawAreaFromBox) . M.elems . getCanvasInfoMap $ st0- if xinputbool- then mapM_ (flip widgetSetExtensionEvents [ExtensionEventsAll]) canvases- else mapM_ (flip widgetSetExtensionEvents [ExtensionEventsNone]) canvases- -- - menubar <- uiManagerGetWidget ui "/ui/menubar" - >>= maybe (error "GUI.hs:no menubar") return - toolbar1 <- uiManagerGetWidget ui "/ui/toolbar1" - >>= maybe (error "GUI.hs:no toolbar1") return - toolbar2 <- uiManagerGetWidget ui "/ui/toolbar2"- >>= maybe (error "GUI.hs:no toolbar2") return - -- - ebox <- eventBoxNew- label <- labelNew (Just "drag me")- containerAdd ebox label - dragSourceSet ebox [Button1] [ActionCopy]- dragSourceSetIconStock ebox stockIndex- dragSourceAddTextTargets ebox- ebox `on` dragBegin $ \_dc -> do - liftIO $ putStrLn "dragging"- ebox `on` dragDataGet $ \_dc _iid _ts -> do + Gtk.initGUI+ window <- Gtk.windowNew + Gtk.windowSetDefaultSize window 800 400+ cfg <- loadConfigFile + devlst <- initDevice cfg + maxundo <- getMaxUndo cfg >>= maybe (return 50) (return . id)+ xinputbool <- getXInputConfig cfg + varcsr <- getPenConfig cfg+ (usepz,uselyr) <- getWidgetConfig cfg + (tref,st0,ui,vbox) <- initCoroutine devlst window mhook maxundo (xinputbool,usepz,uselyr,varcsr) + setTitleFromFileName st0+ -- need for refactoring+ mapM_ (\(x,y :: Simple Lens Settings Bool) -> lensSetToggleUIForFlag x (settings.y) st0 )+ [ ("UXINPUTA", doesUseXInput) + , ("HANDA" , doesUseTouch)+ , ("POPMENUA", doesUsePopUpMenu)+ , ("EBDIMGA" , doesEmbedImage)+ , ("EBDPDFA" , doesEmbedPDF)+ ] + setToggleUIForFlag "TOGGLENETSRCA" False st0+ -- + let canvases = map (getDrawAreaFromBox) . M.elems . view (unitHoodles.currentUnit.cvsInfoMap) $ st0+#ifndef GTK3 + if xinputbool+ then mapM_ (flip Gtk.widgetSetExtensionEvents [Gtk.ExtensionEventsAll]) canvases+ else mapM_ (flip Gtk.widgetSetExtensionEvents [Gtk.ExtensionEventsNone]) canvases+#endif+ --+ outerLayout ui vbox st0 + window `Gtk.on` Gtk.deleteEvent $ do+ liftIO $ eventHandler tref (UsrEv (Menu MenuQuit))+ return True+ Gtk.widgetShowAll window++ forkIO $ clock (eventHandler tref)+ let mainaction = eventHandler tref (UsrEv (Initialized mfname)) >> Gtk.mainGUI + mainaction `catch` \(_e :: SomeException) -> do + homepath <- getEnv "HOME"+ let dir = homepath </> ".hoodle.d"+ createDirectoryIfMissing False dir+ outh <- openFile (dir </> "error.log") WriteMode + hPutStrLn outh "error occured"+ hClose outh + return ()+++clock :: (AllEvent -> IO ()) -> IO ()+clock evhandler = forever $ do + threadDelay 1000000+ Gtk.postGUIAsync (evhandler (SysEv ClockUpdateEvent))++++outerLayout :: Gtk.UIManager -> Gtk.VBox -> HoodleState -> IO ()+outerLayout ui vbox xst = do + let notebook = view rootNotebook xst+ mstatusbar = view statusBar xst+ menubar <- Gtk.uiManagerGetWidget ui "/ui/menubar" + >>= maybe (error "GUI.hs:no menubar") return + toolbar1 <- Gtk.uiManagerGetWidget ui "/ui/toolbar1" + >>= maybe (error "GUI.hs:no toolbar1") return + toolbar2 <- Gtk.uiManagerGetWidget ui "/ui/toolbar2"+ >>= maybe (error "GUI.hs:no toolbar2") return + -- + ebox <- Gtk.eventBoxNew+ label <- Gtk.labelNew (Just "drag me")+ Gtk.containerAdd ebox label + Gtk.dragSourceSet ebox [Gtk.Button1] [Gtk.ActionCopy]+ Gtk.dragSourceSetIconStock ebox Gtk.stockIndex+ Gtk.dragSourceAddTextTargets ebox+ -- ebox `on` dragBegin $ \_dc -> do + -- liftIO $ putStrLn "dragging"+ ebox `Gtk.on` Gtk.dragDataGet $ \_dc _iid _ts -> do -- very dirty solution but.. minfo <- liftIO $ do ref <- newIORef (Nothing :: Maybe String)- view callBack st0 (UsrEv (GetHoodleFileInfo ref))+ view callBack xst (UsrEv (GetHoodleFileInfo ref)) readIORef ref- mapM_ (selectionDataSetText >=> const (return ())) minfo- --- -- - hbox <- hBoxNew False 0 - boxPackStart hbox toolbar1 PackGrow 0- boxPackStart hbox ebox PackNatural 0- containerAdd window vbox- boxPackStart vbox menubar PackNatural 0 - boxPackStart vbox hbox PackNatural 0- boxPackStart vbox toolbar2 PackNatural 0 - boxPackEnd vbox statusbar PackNatural 0 - boxPackStart vbox (view rootWindow st0) PackGrow 0 - window `on` deleteEvent $ do- liftIO $ eventHandler tref (UsrEv (Menu MenuQuit))- return True- widgetShowAll window- -- - -- this is a test for asynchronous events- -- - forkIO $ forever $ do - threadDelay 1000000- -- putStrLn "event!"- postGUIAsync (eventHandler tref (SysEv ClockUpdateEvent))- - -- - -- test end- -- - let mainaction = do eventHandler tref (UsrEv (Initialized mfname))- mainGUI - mainaction `catch` \(_e :: SomeException) -> do - homepath <- getEnv "HOME"- let dir = homepath </> ".hoodle.d"- createDirectoryIfMissing False dir- outh <- openFile (dir </> "error.log") WriteMode - hPutStrLn outh "error occured"- hClose outh - return ()+ traverse Gtk.selectionDataSetText minfo >> return () + -- + hbox <- Gtk.hBoxNew False 0 + Gtk.boxPackStart hbox toolbar1 Gtk.PackGrow 0+ Gtk.boxPackStart hbox ebox Gtk.PackNatural 0+ Gtk.boxPackStart vbox menubar Gtk.PackNatural 0 + Gtk.boxPackStart vbox hbox Gtk.PackNatural 0+ Gtk.boxPackStart vbox toolbar2 Gtk.PackNatural 0 + forM_ mstatusbar $ \statusbar-> Gtk.boxPackEnd vbox statusbar Gtk.PackNatural 0+ --+ Gtk.boxPackStart vbox notebook Gtk.PackGrow 0
src/Hoodle/GUI/Menu.hs view
@@ -1,11 +1,13 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} ----------------------------------------------------------------------------- -- | -- Module : Hoodle.GUI.Menu --- Copyright : (c) 2011-2014 Ian-Woo Kim+-- Copyright : (c) 2011-2015 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -19,8 +21,8 @@ -- from other packages import Control.Lens (set) import Control.Monad-import Graphics.UI.Gtk hiding (set,get)-import qualified Graphics.UI.Gtk as Gtk (set)+import qualified Data.Foldable as F (forM_)+import qualified Graphics.UI.Gtk as Gtk import System.FilePath -- from hoodle-platform import Data.Hoodle.Predefined @@ -34,7 +36,7 @@ justMenu = Just . Menu -iconList :: [ (String,String) ]+iconList :: [ (String,Gtk.StockId) ] iconList = [ ("fullscreen.png" , "myfullscreen") , ("pencil.png" , "mypen") , ("eraser.png" , "myeraser")@@ -66,102 +68,108 @@ ] -- | -viewmods :: [RadioActionEntry] -viewmods = [ RadioActionEntry "CONTA" "Continuous" Nothing Nothing Nothing 0- , RadioActionEntry "ONEPAGEA" "One Page" Nothing Nothing Nothing 1+viewmods :: [Gtk.RadioActionEntry] +viewmods = [ Gtk.RadioActionEntry "CONTA" "Continuous" Nothing Nothing Nothing 0+ , Gtk.RadioActionEntry "ONEPAGEA" "One Page" Nothing Nothing Nothing 1 ] -- | -pointmods :: [RadioActionEntry] -pointmods = [ RadioActionEntry "PENVERYFINEA" "Very fine" Nothing Nothing Nothing 0- , RadioActionEntry "PENFINEA" "Fine" (Just "mythin") Nothing Nothing 1+pointmods :: [Gtk.RadioActionEntry] +pointmods = [ Gtk.RadioActionEntry "PENVERYFINEA" "Very fine" Nothing Nothing Nothing 0+ , Gtk.RadioActionEntry "PENFINEA" "Fine" (Just "mythin") Nothing Nothing 1 - , RadioActionEntry "PENTHICKA" "Thick" (Just "mythick") Nothing Nothing 3 - , RadioActionEntry "PENVERYTHICKA" "Very Thick" Nothing Nothing Nothing 4 - , RadioActionEntry "PENULTRATHICKA" "Ultra Thick" Nothing Nothing Nothing 5 - , RadioActionEntry "PENMEDIUMA" "Medium" (Just "mymedium") Nothing Nothing 2 --- , RadioActionEntry "NOWIDTH" "Unknown" Nothing Nothing Nothing 999 + , Gtk.RadioActionEntry "PENTHICKA" "Thick" (Just "mythick") Nothing Nothing 3 + , Gtk.RadioActionEntry "PENVERYTHICKA" "Very Thick" Nothing Nothing Nothing 4 + , Gtk.RadioActionEntry "PENULTRATHICKA" "Ultra Thick" Nothing Nothing Nothing 5 + , Gtk.RadioActionEntry "PENMEDIUMA" "Medium" (Just "mymedium") Nothing Nothing 2 +-- , Gtk.RadioActionEntry "NOWIDTH" "Unknown" Nothing Nothing Nothing 999 ] -- | -penmods :: [RadioActionEntry] -penmods = [ RadioActionEntry "PENA" "Pen" (Just "mypen") Nothing Nothing 0 - , RadioActionEntry "ERASERA" "Eraser" (Just "myeraser") Nothing Nothing 1- , RadioActionEntry "HIGHLTA" "Highlighter" (Just "myhighlighter") Nothing Nothing 2--- , RadioActionEntry "TEXTA" "Text" (Just "mytext") Nothing Nothing 3 - , RadioActionEntry "SELREGNA" "Select Region" (Just "mylasso") Nothing Nothing 4- , RadioActionEntry "SELRECTA" "Select Rectangle" (Just "myrectselect") Nothing Nothing 5- , RadioActionEntry "VERTSPA" "Vertical Space" (Just "mystretch") Nothing Nothing 6+penmods :: [Gtk.RadioActionEntry] +penmods = [ Gtk.RadioActionEntry "PENA" "Pen" (Just "mypen") Nothing Nothing 0 + , Gtk.RadioActionEntry "ERASERA" "Eraser" (Just "myeraser") Nothing Nothing 1+ , Gtk.RadioActionEntry "HIGHLTA" "Highlighter" (Just "myhighlighter") Nothing Nothing 2+-- , Gtk.RadioActionEntry "TEXTA" "Text" (Just "mytext") Nothing Nothing 3 + , Gtk.RadioActionEntry "SELREGNA" "Select Region" (Just "mylasso") Nothing Nothing 4+ , Gtk.RadioActionEntry "SELRECTA" "Select Rectangle" (Just "myrectselect") Nothing Nothing 5+ , Gtk.RadioActionEntry "VERTSPA" "Vertical Space" (Just "mystretch") Nothing Nothing 6 ] --- , RadioActionEntry "HANDA" "Hand Tool" (Just "myhand") Nothing Nothing 7+-- , Gtk.RadioActionEntry "HANDA" "Hand Tool" (Just "myhand") Nothing Nothing 7 -- | -colormods :: [RadioActionEntry]-colormods = [ RadioActionEntry "BLUEA" "Blue" (Just "myblue") Nothing Nothing 1- , RadioActionEntry "REDA" "Red" (Just "myred") Nothing Nothing 2- , RadioActionEntry "GREENA" "Green" (Just "mygreen") Nothing Nothing 3- , RadioActionEntry "GRAYA" "Gray" (Just "mygray") Nothing Nothing 4- , RadioActionEntry "LIGHTBLUEA" "Lightblue" (Just "mylightblue") Nothing Nothing 5 - , RadioActionEntry "LIGHTGREENA" "Lightgreen" (Just "mylightgreen") Nothing Nothing 6- , RadioActionEntry "MAGENTAA" "Magenta" (Just "mymagenta") Nothing Nothing 7- , RadioActionEntry "ORANGEA" "Orange" (Just "myorange") Nothing Nothing 8- , RadioActionEntry "YELLOWA" "Yellow" (Just "myyellow") Nothing Nothing 9- , RadioActionEntry "WHITEA" "White" (Just "mywhite") Nothing Nothing 10- , RadioActionEntry "BLACKA" "Black" (Just "myblack") Nothing Nothing 0 ---- , RadioActionEntry "NOCOLOR" "Unknown" Nothing Nothing Nothing 999 +colormods :: [Gtk.RadioActionEntry]+colormods = [ Gtk.RadioActionEntry "BLUEA" "Blue" (Just "myblue") Nothing Nothing 1+ , Gtk.RadioActionEntry "REDA" "Red" (Just "myred") Nothing Nothing 2+ , Gtk.RadioActionEntry "GREENA" "Green" (Just "mygreen") Nothing Nothing 3+ , Gtk.RadioActionEntry "GRAYA" "Gray" (Just "mygray") Nothing Nothing 4+ , Gtk.RadioActionEntry "LIGHTBLUEA" "Lightblue" (Just "mylightblue") Nothing Nothing 5 + , Gtk.RadioActionEntry "LIGHTGREENA" "Lightgreen" (Just "mylightgreen") Nothing Nothing 6+ , Gtk.RadioActionEntry "MAGENTAA" "Magenta" (Just "mymagenta") Nothing Nothing 7+ , Gtk.RadioActionEntry "ORANGEA" "Orange" (Just "myorange") Nothing Nothing 8+ , Gtk.RadioActionEntry "YELLOWA" "Yellow" (Just "myyellow") Nothing Nothing 9+ , Gtk.RadioActionEntry "WHITEA" "White" (Just "mywhite") Nothing Nothing 10+ , Gtk.RadioActionEntry "BLACKA" "Black" (Just "myblack") Nothing Nothing 0 +--- , Gtk.RadioActionEntry "NOCOLOR" "Unknown" Nothing Nothing Nothing 999 ] -- | -bkgstyles :: [RadioActionEntry] -bkgstyles = [ RadioActionEntry "BKGGRAPHA" "Graph" Nothing Nothing Nothing 3 - , RadioActionEntry "BKGPLAINA" "Plain" Nothing Nothing Nothing 0- , RadioActionEntry "BKGLINEDA" "Lined" Nothing Nothing Nothing 1- , RadioActionEntry "BKGRULEDA" "Ruled" Nothing Nothing Nothing 2 +bkgstyles :: [Gtk.RadioActionEntry] +bkgstyles = [ Gtk.RadioActionEntry "BKGGRAPHA" "Graph" Nothing Nothing Nothing 3 + , Gtk.RadioActionEntry "BKGPLAINA" "Plain" Nothing Nothing Nothing 0+ , Gtk.RadioActionEntry "BKGLINEDA" "Lined" Nothing Nothing Nothing 1+ , Gtk.RadioActionEntry "BKGRULEDA" "Ruled" Nothing Nothing Nothing 2 ] +newpagemods :: [Gtk.RadioActionEntry] +newpagemods = [ Gtk.RadioActionEntry "NEWPAGEPLAINA" "Plain page" Nothing Nothing Nothing 0 + , Gtk.RadioActionEntry "NEWPAGELASTA" "Last page" Nothing Nothing Nothing 1+ , Gtk.RadioActionEntry "NEWPAGECYCLEA" "Cycle page" Nothing Nothing Nothing 2+ ]++ -- | -iconResourceAdd :: IconFactory -> FilePath -> (FilePath, StockId) - -> IO ()+iconResourceAdd :: Gtk.IconFactory -> FilePath -> (FilePath, Gtk.StockId) -> IO () iconResourceAdd iconfac resdir (fp,stid) = do - myIconSource <- iconSourceNew - iconSourceSetFilename myIconSource (resdir </> fp)- iconSourceSetSize myIconSource IconSizeLargeToolbar- myIconSourceSmall <- iconSourceNew - iconSourceSetFilename myIconSourceSmall (resdir </> fp)- iconSourceSetSize myIconSource IconSizeMenu- myIconSet <- iconSetNew - iconSetAddSource myIconSet myIconSource - iconSetAddSource myIconSet myIconSourceSmall- iconFactoryAdd iconfac stid myIconSet+ myIconSource <- Gtk.iconSourceNew + Gtk.iconSourceSetFilename myIconSource (resdir </> fp)+ Gtk.iconSourceSetSize myIconSource Gtk.IconSizeLargeToolbar+ myIconSourceSmall <- Gtk.iconSourceNew + Gtk.iconSourceSetFilename myIconSourceSmall (resdir </> fp)+ Gtk.iconSourceSetSize myIconSource Gtk.IconSizeMenu+ myIconSet <- Gtk.iconSetNew + Gtk.iconSetAddSource myIconSet myIconSource + Gtk.iconSetAddSource myIconSet myIconSourceSmall+ Gtk.iconFactoryAdd iconfac stid myIconSet -- | actionNewAndRegisterRef :: EventVar -> String -> String - -> Maybe String -> Maybe StockId+ -> Maybe String -> Maybe Gtk.StockId -> Maybe UserEvent - -> IO Action+ -> IO Gtk.Action actionNewAndRegisterRef evar name label tooltip stockId myevent = do - a <- actionNew name label tooltip stockId + a <- Gtk.actionNew name label tooltip stockId case myevent of Nothing -> return a Just ev -> do - a `on` actionActivated $ do + a `Gtk.on` Gtk.actionActivated $ do eventHandler evar (UsrEv ev) return a -- | -getMenuUI :: EventVar -> IO (UIManager,UIComponentSignalHandler)+getMenuUI :: EventVar -> IO (Gtk.UIManager,UIComponentSignalHandler) getMenuUI evar = do let actionNewAndRegister = actionNewAndRegisterRef evar -- icons - myiconfac <- iconFactoryNew - iconFactoryAddDefault myiconfac + myiconfac <- Gtk.iconFactoryNew + Gtk.iconFactoryAddDefault myiconfac resDir <- getDataDir >>= return . (</> "resource") mapM_ (iconResourceAdd myiconfac resDir) iconList fma <- actionNewAndRegister "FMA" "File" Nothing Nothing Nothing@@ -173,15 +181,16 @@ tma <- actionNewAndRegister "TMA" "Tool" Nothing Nothing Nothing verma <- actionNewAndRegister "VERMA" "Version" Nothing Nothing Nothing oma <- actionNewAndRegister "OMA" "Option" Nothing Nothing Nothing+ wma <- actionNewAndRegister "WMA" "Window" Nothing Nothing Nothing hma <- actionNewAndRegister "HMA" "Help" Nothing Nothing Nothing --------------- -- file menu -- ---------------- newa <- actionNewAndRegister "NEWA" "New" (Just "Just a Stub") (Just stockNew) (justMenu MenuNew)- opena <- actionNewAndRegister "OPENA" "Open" (Just "Just a Stub") (Just stockOpen) (justMenu MenuOpen)- savea <- actionNewAndRegister "SAVEA" "Save" (Just "Just a Stub") (Just stockSave) (justMenu MenuSave)- saveasa <- actionNewAndRegister "SAVEASA" "Save As" (Just "Just a Stub") (Just stockSaveAs) (justMenu MenuSaveAs)+ newa <- actionNewAndRegister "NEWA" "New" (Just "Just a Stub") (Just Gtk.stockNew) (justMenu MenuNew)+ opena <- actionNewAndRegister "OPENA" "Open" (Just "Just a Stub") (Just Gtk.stockOpen) (justMenu MenuOpen)+ savea <- actionNewAndRegister "SAVEA" "Save" (Just "Just a Stub") (Just Gtk.stockSave) (justMenu MenuSave)+ saveasa <- actionNewAndRegister "SAVEASA" "Save As" (Just "Just a Stub") (Just Gtk.stockSaveAs) (justMenu MenuSaveAs) printa <- actionNewAndRegister "PRINTA" "Print" (Just "Just a Stub") Nothing (justMenu MenuPrint) -- exporta <- actionNewAndRegister "EXPORTA" "Export to PDF" (Just "Just a Stub") Nothing (justMenu MenuExport)@@ -192,37 +201,38 @@ reloada <- actionNewAndRegister "RELOADA" "Reload File" (Just "Just a Stub") Nothing (justMenu MenuReload) recenta <- actionNewAndRegister "RECENTA" "Recent Document" (Just "Just a Stub") Nothing (justMenu MenuRecentDocument) --- quita <- actionNewAndRegister "QUITA" "Quit" (Just "Just a Stub") (Just stockQuit) (justMenu MenuQuit)+ quita <- actionNewAndRegister "QUITA" "Quit" (Just "Just a Stub") (Just Gtk.stockQuit) (justMenu MenuQuit) --------------- -- edit menu -- ---------------- undoa <- actionNewAndRegister "UNDOA" "Undo" (Just "Just a Stub") (Just stockUndo) (justMenu MenuUndo)- redoa <- actionNewAndRegister "REDOA" "Redo" (Just "Just a Stub") (Just stockRedo) (justMenu MenuRedo)- cuta <- actionNewAndRegister "CUTA" "Cut" (Just "Just a Stub") (Just stockCut) (justMenu MenuCut)- copya <- actionNewAndRegister "COPYA" "Copy" (Just "Just a Stub") (Just stockCopy) (justMenu MenuCopy)- pastea <- actionNewAndRegister "PASTEA" "Paste" (Just "Just a Stub") (Just stockPaste) (justMenu MenuPaste)- deletea <- actionNewAndRegister "DELETEA" "Delete" (Just "Just a Stub") (Just stockDelete) (justMenu MenuDelete)+ undoa <- actionNewAndRegister "UNDOA" "Undo" (Just "Just a Stub") (Just Gtk.stockUndo) (justMenu MenuUndo)+ redoa <- actionNewAndRegister "REDOA" "Redo" (Just "Just a Stub") (Just Gtk.stockRedo) (justMenu MenuRedo)+ cuta <- actionNewAndRegister "CUTA" "Cut" (Just "Just a Stub") (Just Gtk.stockCut) (justMenu MenuCut)+ copya <- actionNewAndRegister "COPYA" "Copy" (Just "Just a Stub") (Just Gtk.stockCopy) (justMenu MenuCopy)+ pastea <- actionNewAndRegister "PASTEA" "Paste" (Just "Just a Stub") (Just Gtk.stockPaste) (justMenu MenuPaste)+ deletea <- actionNewAndRegister "DELETEA" "Delete" (Just "Just a Stub") (Just Gtk.stockDelete) (justMenu MenuDelete) --------------- -- view menu -- --------------- togpanzooma <- actionNewAndRegister "TOGPANZOOMA" "Show/Hide Zoom Widget" (Just "Just a stub") Nothing (justMenu MenuTogglePanZoomWidget)+ togscra <- actionNewAndRegister "TOGSCRA" "Show/Hide Scroll Widget" (Just "Just a stub") Nothing (justMenu MenuToggleScrollWidget) -- zooma <- actionNewAndRegister "ZOOMA" "Zoom" (Just "Just a Stub") Nothing Nothing -- (justMenu MenuZoom)- zmina <- actionNewAndRegister "ZMINA" "Zoom In" (Just "Zoom In") (Just stockZoomIn) (justMenu MenuZoomIn)- zmouta <- actionNewAndRegister "ZMOUTA" "Zoom Out" (Just "Zoom Out") (Just stockZoomOut) (justMenu MenuZoomOut)- nrmsizea <- actionNewAndRegister "NRMSIZEA" "Normal Size" (Just "Normal Size") (Just stockZoom100) (justMenu MenuNormalSize)- pgwdtha <- actionNewAndRegister "PGWDTHA" "Page Width" (Just "Page Width") (Just stockZoomFit) (justMenu MenuPageWidth)+ zmina <- actionNewAndRegister "ZMINA" "Zoom In" (Just "Zoom In") (Just Gtk.stockZoomIn) (justMenu MenuZoomIn)+ zmouta <- actionNewAndRegister "ZMOUTA" "Zoom Out" (Just "Zoom Out") (Just Gtk.stockZoomOut) (justMenu MenuZoomOut)+ nrmsizea <- actionNewAndRegister "NRMSIZEA" "Normal Size" (Just "Normal Size") (Just Gtk.stockZoom100) (justMenu MenuNormalSize)+ pgwdtha <- actionNewAndRegister "PGWDTHA" "Page Width" (Just "Page Width") (Just Gtk.stockZoomFit) (justMenu MenuPageWidth) pgheighta <- actionNewAndRegister "PGHEIGHTA" "Page Height" (Just "Page Height") Nothing (justMenu MenuPageHeight)- setzma <- actionNewAndRegister "SETZMA" "Set Zoom" (Just "Set Zoom") (Just stockFind) (justMenu MenuSetZoom)+ setzma <- actionNewAndRegister "SETZMA" "Set Zoom" (Just "Set Zoom") (Just Gtk.stockFind) (justMenu MenuSetZoom) -- fscra <- actionNewAndRegister "FSCRA" "Full Screen" (Just "Just a Stub") (Just "myfullscreen") (justMenu MenuFullScreen) --- fstpagea <- actionNewAndRegister "FSTPAGEA" "First Page" (Just "Just a Stub") (Just stockGotoFirst) (justMenu MenuFirstPage)- prvpagea <- actionNewAndRegister "PRVPAGEA" "Previous Page" (Just "Just a Stub") (Just stockGoBack) (justMenu MenuPreviousPage)- nxtpagea <- actionNewAndRegister "NXTPAGEA" "Next Page" (Just "Just a Stub") (Just stockGoForward) (justMenu MenuNextPage)- lstpagea <- actionNewAndRegister "LSTPAGEA" "Last Page" (Just "Just a Stub") (Just stockGotoLast) (justMenu MenuLastPage)+ fstpagea <- actionNewAndRegister "FSTPAGEA" "First Page" (Just "Just a Stub") (Just Gtk.stockGotoFirst) (justMenu MenuFirstPage)+ prvpagea <- actionNewAndRegister "PRVPAGEA" "Previous Page" (Just "Just a Stub") (Just Gtk.stockGoBack) (justMenu MenuPreviousPage)+ nxtpagea <- actionNewAndRegister "NXTPAGEA" "Next Page" (Just "Just a Stub") (Just Gtk.stockGoForward) (justMenu MenuNextPage)+ lstpagea <- actionNewAndRegister "LSTPAGEA" "Last Page" (Just "Just a Stub") (Just Gtk.stockGotoLast) (justMenu MenuLastPage) -- hsplita <- actionNewAndRegister "HSPLITA" "Clone View Horizontally" (Just "horizontal split") Nothing (justMenu MenuHSplit) vsplita <- actionNewAndRegister "VSPLITA" "Clone View Vertically" (Just "vertical split") Nothing (justMenu MenuVSplit)@@ -240,16 +250,13 @@ gotolayera <- actionNewAndRegister "GOTOLAYERA" "Goto Layer" (Just "Just a Stub") Nothing (justMenu MenuGotoLayer) dellyra <- actionNewAndRegister "DELLYRA" "Delete Layer" (Just "Just a Stub") Nothing (justMenu MenuDeleteLayer) - -- shwlayera <- actionNewAndRegister "SHWLAYERA" "Show Layer" (Just "Just a Stub") Nothing (justMenu MenuShowLayer)- -- hidlayera <- actionNewAndRegister "HIDLAYERA" "Hide Layer" (Just "Just a Stub") Nothing (justMenu MenuHideLayer)-- ----------------- -- image menu --+ -- embed menu -- ---------------- ldpnga <- actionNewAndRegister "LDIMGA" "Load PNG or JPG Image" (Just "Just a Stub") Nothing (justMenu MenuLoadPNGorJPG) ldsvga <- actionNewAndRegister "LDSVGA" "Load SVG Image" (Just "Just a Stub") Nothing (justMenu MenuLoadSVG)+ ldimgbkga <- actionNewAndRegister "LDIMGBKGA" "Make Title Page from Image" (Just "Just a Stub") Nothing (justMenu MenuLoadImageBackground) ldpreimga <- actionNewAndRegister "LDPREIMGA" "Embed Predefined Image File" (Just "Just a Stub") Nothing (justMenu MenuEmbedPredefinedImage) ldpreimg2a <- actionNewAndRegister "LDPREIMG2A" "Embed Predefined Image File 2" (Just "Just a Stub") Nothing (justMenu MenuEmbedPredefinedImage2) ldpreimg3a <- actionNewAndRegister "LDPREIMG3A" "Embed Predefined Image File 3" (Just "Just a Stub") Nothing (justMenu MenuEmbedPredefinedImage3)@@ -257,17 +264,37 @@ texta <- actionNewAndRegister "TEXTA" "Text" (Just "Text") (Just "mytext") (justMenu MenuText) textsrca <- actionNewAndRegister "TEXTSRCA" "Embed Text Source" (Just "Just a Stub") Nothing (justMenu MenuEmbedTextSource) editsrca <- actionNewAndRegister "EDITSRCA" "Edit text source" (Just "Just a Stub") Nothing (justMenu MenuEditEmbedTextSource)+#ifdef HUB editnetsrca <- actionNewAndRegister "EDITNETSRCA" "Network edit text source" (Just "Just a Stub") Nothing (justMenu MenuEditNetEmbedTextSource)-+#else+ editnetsrca <- actionNewAndRegister "EDITNETSRCA" "Network edit text source" (Just "Just a Stub") Nothing (justMenu MenuDefault)+#endif textfromsrca <- actionNewAndRegister "TEXTFROMSRCA" "Text From Source" (Just "Just a Stub") Nothing (justMenu MenuTextFromSource) ++ togglenetsrca <- Gtk.toggleActionNew ("TOGGLENETSRCA" :: String) "Toggle network edit text source" (Just "Just a Stub") Nothing+#ifdef HUB+ togglenetsrca `Gtk.on` Gtk.actionToggled $ do+ eventHandler evar (UsrEv (Menu MenuToggleNetworkEditSource))+#else+ togglenetsrca `Gtk.on` Gtk.actionToggled $ do+ eventHandler evar (UsrEv (Menu MenuDefault))+#endif latexa <- actionNewAndRegister "LATEXA" "LaTeX" (Just "Just a Stub") (Just "mylatex") (justMenu MenuLaTeX)+#ifdef HUB latexneta <- actionNewAndRegister "LATEXNETA" "LaTeX Network" (Just "Just a Stub") (Just "mylatex") (justMenu MenuLaTeXNetwork) +#else+ latexneta <- actionNewAndRegister "LATEXNETA" "LaTeX Network" (Just "Just a Stub") (Just "mylatex") (justMenu MenuDefault) +#endif combinelatexa <- actionNewAndRegister "COMBINELATEXA" "Combine LaTeX texts to ..." (Just "Just a Stub") Nothing (justMenu MenuCombineLaTeX) latexfromsrca <- actionNewAndRegister "LATEXFROMSRCA" "LaTeX From Source" (Just "Just a Stub") Nothing (justMenu MenuLaTeXFromSource) + updatelatexa <- actionNewAndRegister "UPDATELATEXA" "Update LaTeX" (Just "Just a Stub") Nothing (justMenu MenuUpdateLaTeX) - -- page menu + ---------------+ -- page menu --+ ---------------+ newpgba <- actionNewAndRegister "NEWPGBA" "New Page Before" (Just "Just a Stub") Nothing (justMenu MenuNewPageBefore) newpgaa <- actionNewAndRegister "NEWPGAA" "New Page After" (Just "Just a Stub") Nothing (justMenu MenuNewPageAfter) newpgea <- actionNewAndRegister "NEWPGEA" "New Page At End" (Just "Just a Stub") Nothing (justMenu MenuNewPageAtEnd)@@ -278,26 +305,17 @@ ppstya <- actionNewAndRegister "PPSTYA" "Paper Style" Nothing Nothing Nothing apallpga<- actionNewAndRegister "APALLPGA" "Apply To All Pages" (Just "Just a Stub") Nothing (justMenu MenuApplyToAllPages) embedbkgpdfa <- actionNewAndRegister "EMBEDBKGPDFA" "Embed All PDF backgroound" (Just "Just a Stub") Nothing (justMenu MenuEmbedAllPDFBkg)- -- ldbkga <- actionNewAndRegister "LDBKGA" "Load Background" (Just "Just a Stub") Nothing (justMenu MenuLoadBackground)- -- bkgscrshta <- actionNewAndRegister "BKGSCRSHTA" "Background Screenshot" (Just "Just a Stub") Nothing (justMenu MenuBackgroundScreenshot) defppa <- actionNewAndRegister "DEFPPA" "Default Paper" (Just "Just a Stub") Nothing (justMenu MenuDefaultPaper) setdefppa <- actionNewAndRegister "SETDEFPPA" "Set As Default" (Just "Just a Stub") Nothing (justMenu MenuSetAsDefaultPaper) -- tools menu- linka <- actionNewAndRegister "LINKA" "Add Link" (Just "Add Link") (Just stockIndex) (justMenu MenuAddLink)+ linka <- actionNewAndRegister "LINKA" "Add Link" (Just "Add Link") (Just Gtk.stockIndex) (justMenu MenuAddLink) anchora <- actionNewAndRegister "ANCHORA" "Add Anchor" (Just "Add Anchor") Nothing (justMenu MenuAddAnchor) listanchora <- actionNewAndRegister "LISTANCHORA" "List Anchors" (Just "List Anchors") Nothing (justMenu MenuListAnchors)-- -- shpreca <- actionNewAndRegister "SHPRECA" "Shape Recognizer" (Just "Just a Stub") (Just "myshapes") (justMenu MenuShapeRecognizer)- -- rulera <- actionNewAndRegister "RULERA" "Ruler" (Just "Just a Stub") (Just "myruler") (justMenu MenuRuler) handreca <- actionNewAndRegister "HANDRECA" "Hoodlet load via Handwriting Recognition" (Just "Just a Stub") (Just "myshapes") (justMenu MenuHandwritingRecognitionDialog) - - -- selregna <- actionNewAndRegister "SELREGNA" "Select Region" (Just "Just a Stub") (Just "mylasso") (justMenu MenuSelectRegion)- -- selrecta <- actionNewAndRegister "SELRECTA" "Select Rectangle" (Just "Just a Stub") (Just "myrectselect") (justMenu MenuSelectRectangle)- -- vertspa <- actionNewAndRegister "VERTSPA" "Vertical Space" (Just "Just a Stub") (Just "mystretch") (justMenu MenuVerticalSpace) clra <- actionNewAndRegister "CLRA" "Color" (Just "Just a Stub") Nothing Nothing- clrpcka <- actionNewAndRegister "CLRPCKA" "Color Picker.." (Just "Just a Stub") (Just stockSelectColor) (justMenu MenuColorPicker ) + clrpcka <- actionNewAndRegister "CLRPCKA" "Color Picker.." (Just "Just a Stub") (Just Gtk.stockSelectColor) (justMenu MenuColorPicker ) penopta <- actionNewAndRegister "PENOPTA" "Pen Options" (Just "Just a Stub") Nothing (justMenu MenuPenOptions) erasropta <- actionNewAndRegister "ERASROPTA" "Eraser Options" (Just "Just a Stub") Nothing (justMenu MenuEraserOptions) hiltropta <- actionNewAndRegister "HILTROPTA" "Highlighter Options" (Just "Just a Stub") Nothing (justMenu MenuHighlighterOptions)@@ -307,9 +325,9 @@ defhiltra <- actionNewAndRegister "DEFHILTRA" "Default Highlighter" (Just "Just a Stub") Nothing (justMenu MenuDefaultHighlighter) deftxta <- actionNewAndRegister "DEFTXTA" "Default Text" (Just "Just a Stub") Nothing (justMenu MenuDefaultText) setdefopta <- actionNewAndRegister "SETDEFOPTA" "Set As Default" (Just "Just a Stub") Nothing (justMenu MenuSetAsDefaultOption)- relauncha <- actionNewAndRegister "RELAUNCHA" "Relaunch Application" (Just "Just a Stub") Nothing (justMenu MenuRelaunch) + ------------------ -- version menu -- ------------------@@ -323,227 +341,242 @@ ----------------- -- option menu -- ------------------ uxinputa <- toggleActionNew "UXINPUTA" "Use XInput" (Just "Just a Stub") Nothing - uxinputa `on` actionToggled $ do + uxinputa <- Gtk.toggleActionNew ("UXINPUTA" :: String) "Use XInput" (Just "Just a Stub") Nothing + uxinputa `Gtk.on` Gtk.actionToggled $ do eventHandler evar (UsrEv (Menu MenuUseXInput)) -- handa <- actionNewAndRegister "HANDA" "Use Touch" (Just "Use touch") (Just "myhand") (justMenu MenuUseTouch) - handa <- toggleActionNew "HANDA" "Use Touch" (Just "Toggle touch") (Just "myhand") - handa `on` actionToggled $ do + handa <- Gtk.toggleActionNew ("HANDA" :: String) "Use Touch" (Just "Toggle touch") (Just "myhand") + handa `Gtk.on` Gtk.actionToggled $ do eventHandler evar (UsrEv (Menu MenuUseTouch))- smthscra <- toggleActionNew "SMTHSCRA" "Smooth Scrolling" (Just "Just a stub") Nothing- smthscra `on` actionToggled $ do - eventHandler evar (UsrEv (Menu MenuSmoothScroll))- popmenua <- toggleActionNew "POPMENUA" "Use Popup Menu" (Just "Just a stub") Nothing- popmenua `on` actionToggled $ do + -- smthscra <- Gtk.toggleActionNew ("SMTHSCRA" :: String) "Smooth Scrolling" (Just "Just a stub") Nothing+ -- smthscra `Gtk.on` Gtk.actionToggled $ do + -- eventHandler evar (UsrEv (Menu MenuSmoothScroll))+ popmenua <- Gtk.toggleActionNew ("POPMENUA" :: String) "Use Popup Menu" (Just "Just a stub") Nothing+ popmenua `Gtk.on` Gtk.actionToggled $ do eventHandler evar (UsrEv (Menu MenuUsePopUpMenu))- ebdimga <- toggleActionNew "EBDIMGA" "Embed PNG/JPG Image" (Just "Just a stub") Nothing- ebdimga `on` actionToggled $ do + ebdimga <- Gtk.toggleActionNew ("EBDIMGA" :: String) "Embed PNG/JPG Image" (Just "Just a stub") Nothing+ ebdimga `Gtk.on` Gtk.actionToggled $ do eventHandler evar (UsrEv (Menu MenuEmbedImage))- ebdpdfa <- toggleActionNew "EBDPDFA" "Embed PDF" (Just "Just a stub") Nothing- ebdpdfa `on` actionToggled $ do + ebdpdfa <- Gtk.toggleActionNew ("EBDPDFA" :: String) "Embed PDF" (Just "Just a stub") Nothing+ ebdpdfa `Gtk.on` Gtk.actionToggled $ do eventHandler evar (UsrEv (Menu MenuEmbedPDF))- flwlnka <- toggleActionNew "FLWLNKA" "Follow Links" (Just "Just a stub") Nothing- flwlnka `on` actionToggled $ do + flwlnka <- Gtk.toggleActionNew ("FLWLNKA" :: String) "Follow Links" (Just "Just a stub") Nothing+ flwlnka `Gtk.on` Gtk.actionToggled $ do eventHandler evar (UsrEv (Menu MenuFollowLinks)) - keepratioa <- toggleActionNew "KEEPRATIOA" "Keep Aspect Ratio" (Just "Just a stub") Nothing- keepratioa `on` actionToggled $ do + keepratioa <- Gtk.toggleActionNew ("KEEPRATIOA" :: String) "Keep Aspect Ratio" (Just "Just a stub") Nothing+ keepratioa `Gtk.on` Gtk.actionToggled $ do eventHandler evar (UsrEv (Menu MenuKeepAspectRatio))- vcursora <- toggleActionNew "VCURSORA" "Use Variable Cursor" (Just "Just a stub") Nothing- vcursora `on` actionToggled $ do + vcursora <- Gtk.toggleActionNew ("VCURSORA" :: String) "Use Variable Cursor" (Just "Just a stub") Nothing+ vcursora `Gtk.on` Gtk.actionToggled $ do eventHandler evar (UsrEv (Menu MenuUseVariableCursor)) -- temporary implementation (later will be as submenus with toggle action. appropriate reflection) togclocka <- actionNewAndRegister "TOGCLOCKA" "Toggle Clock Widget" (Just "Just a stub") Nothing (justMenu MenuToggleClockWidget) - dcrdcorea <- actionNewAndRegister "DCRDCOREA" "Discard Core Events" (Just "Just a Stub") Nothing (justMenu MenuDiscardCoreEvents)- ersrtipa <- actionNewAndRegister "ERSRTIPA" "Eraser Tip" (Just "Just a Stub") Nothing (justMenu MenuEraserTip)- pressrsensa <- toggleActionNew "PRESSRSENSA" "Pressure Sensitivity" (Just "Just a Stub") Nothing - pressrsensa `on` actionToggled $ do + pressrsensa <- Gtk.toggleActionNew ("PRESSRSENSA" :: String) "Pressure Sensitivity" (Just "Just a Stub") Nothing + pressrsensa `Gtk.on` Gtk.actionToggled $ do eventHandler evar (UsrEv (Menu MenuPressureSensitivity)) + newpagemoda <- actionNewAndRegister "NEWPAGEMODEA" "New page mode" Nothing Nothing Nothing+#ifdef DYRE+ relauncha <- actionNewAndRegister "RELAUNCHA" "Relaunch Application" (Just "Just a Stub") Nothing (justMenu MenuRelaunch)+#else+ relauncha <- actionNewAndRegister "RELAUNCHA" "Relaunch Application" (Just "Just a Stub") Nothing (justMenu MenuDefault)+#endif - - - - pghilta <- actionNewAndRegister "PGHILTA" "Page Highlight" (Just "Just a Stub") Nothing (justMenu MenuPageHighlight)- mltpgvwa <- actionNewAndRegister "MLTPGVWA" "Multiple Page View" (Just "Just a Stub") Nothing (justMenu MenuMultiplePageView) - mltpga <- actionNewAndRegister "MLTPGA" "Multiple Pages" (Just "Just a Stub") Nothing (justMenu MenuMultiplePages)- btn2mapa <- actionNewAndRegister "BTN2MAPA" "Button 2 Mapping" (Just "Just a Stub") Nothing (justMenu MenuButton2Mapping)- btn3mapa <- actionNewAndRegister "BTN3MAPA" "Button 3 Mapping" (Just "Just a Stub") Nothing (justMenu MenuButton3Mapping)- antialiasbmpa <- actionNewAndRegister "ANTIALIASBMPA" "Antialiased Bitmaps" (Just "Just a Stub") Nothing (justMenu MenuAntialiasedBitmaps)- prgrsbkga <- actionNewAndRegister "PRGRSBKGA" "Progressive Backgrounds" (Just "Just a Stub") Nothing (justMenu MenuProgressiveBackgrounds)- prntpprulea <- actionNewAndRegister "PRNTPPRULEA" "Print Paper Ruling" (Just "Just a Stub") Nothing (justMenu MenuPrintPaperRuling)- lfthndscrbra <- actionNewAndRegister "LFTHNDSCRBRA" "Left-Handed Scrollbar" (Just "Just a Stub") Nothing (justMenu MenuLeftHandedScrollbar)- shrtnmenua <- actionNewAndRegister "SHRTNMENUA" "Shorten Menus" (Just "Just a Stub") Nothing (justMenu MenuShortenMenus)- autosaveprefa <- actionNewAndRegister "AUTOSAVEPREFA" "Auto-Save Preferences" (Just "Just a Stub") Nothing (justMenu MenuAutoSavePreferences)- saveprefa <- actionNewAndRegister "SAVEPREFA" "Save Preferences" (Just "Just a Stub") Nothing (justMenu MenuSavePreferences)- +#ifdef HUB+ huba <- actionNewAndRegister "HUBA" "Hub" (Just "Just a Stub") Nothing (justMenu MenuHub)+ -- hubsocketa <- actionNewAndRegister "HUBSOCKETA" "Hub Socket" (Just "Just a Stub") Nothing (justMenu MenuHubSocket)+#else+ huba <- actionNewAndRegister "HUBA" "Hub" (Just "Just a Stub") Nothing (justMenu MenuDefault)+ -- hubsocketa <- actionNewAndRegister "HUBSOCKETA" "Hub Socket" (Just "Just a Stub") Nothing (justMenu MenuDefault)+#endif+++ -- window menu+ addtaba <- actionNewAndRegister "ADDTABA" "Add new tab" (Just "Just a Stub") Nothing (justMenu MenuAddTab)+ -- nexttaba <- actionNewAndRegister "NEXTTABA" "Go to next tab" (Just "Just a Stub") Nothing (justMenu MenuNextTab)+ closetaba <- actionNewAndRegister "CLOSETABA" "Close current tab" (Just "Just a Stub") Nothing (justMenu MenuCloseTab)+++ -- help menu abouta <- actionNewAndRegister "ABOUTA" "About" (Just "Just a Stub") Nothing (justMenu MenuAbout) -- others defaulta <- actionNewAndRegister "DEFAULTA" "Default" (Just "Default") (Just "mydefault") (justMenu MenuDefault) - agr <- actionGroupNew "AGR"- mapM_ (actionGroupAddAction agr) - [fma,ema,vma,lma,ima,pma,tma,verma,oma,hma]- mapM_ (actionGroupAddAction agr) + agr <- Gtk.actionGroupNew ("AGR" :: String)+ mapM_ (Gtk.actionGroupAddAction agr) + [fma,ema,vma,lma,ima,pma,tma,verma,oma,wma,hma]+ mapM_ (Gtk.actionGroupAddAction agr) [ undoa, redoa, cuta, copya, pastea, deletea ] - mapM_ (\act -> actionGroupAddActionWithAccel agr act Nothing) + mapM_ (\act -> Gtk.actionGroupAddActionWithAccel agr act (Nothing :: Maybe String)) [ newa, annpdfa, opena, savea, saveasa , reloada, recenta, printa, exporta, synca, versiona, showreva, showida, quita , fscra, zooma, zmina, zmouta, nrmsizea, pgwdtha, pgheighta, setzma- , fstpagea, prvpagea, nxtpagea, lstpagea {- , shwlayera, hidlayera -}+ , fstpagea, prvpagea, nxtpagea, lstpagea , hsplita, vsplita, delcvsa , newpgba, newpgaa, newpgea, delpga, expsvga, newlyra, nextlayera, prevlayera, gotolayera, dellyra, ppsizea, ppclra , ppstya , apallpga, embedbkgpdfa, defppa, setdefppa- , ldpnga, ldsvga, texta, textsrca, editsrca, editnetsrca, textfromsrca- , latexa, latexneta, combinelatexa, latexfromsrca+ , ldpnga, ldsvga, ldimgbkga, texta, textsrca, editsrca, editnetsrca, textfromsrca+ , latexa, latexneta, combinelatexa, latexfromsrca, updatelatexa , ldpreimga, ldpreimg2a, ldpreimg3a- , linka, anchora, listanchora, {- shpreca, rulera, -} handreca, clra, clrpcka, penopta + , linka, anchora, listanchora, handreca, clra, clrpcka, penopta , erasropta, hiltropta, txtfnta, defpena, defersra, defhiltra, deftxta- , setdefopta, relauncha- , togpanzooma, toglayera, togclocka- , dcrdcorea, ersrtipa, pghilta, mltpgvwa- , mltpga, btn2mapa, btn3mapa, antialiasbmpa, prgrsbkga, prntpprulea - , lfthndscrbra, shrtnmenua, autosaveprefa, saveprefa + , setdefopta+ , togpanzooma, togscra, toglayera, togclocka, newpagemoda, relauncha+ , huba -- , hubsocketa+ , addtaba, {- nexttaba, -} closetaba , abouta , defaulta ] - mapM_ (actionGroupAddAction agr) - [ uxinputa, handa, smthscra, popmenua, ebdimga, ebdpdfa, flwlnka, keepratioa, pressrsensa- , vcursora ]- -- actionGroupAddRadioActions agr viewmods 0 (assignViewMode evar)+ mapM_ (Gtk.actionGroupAddAction agr) + [ togglenetsrca, uxinputa, handa, popmenua, ebdimga, ebdpdfa, flwlnka+ , keepratioa, pressrsensa, vcursora ]+ mpgmodconnid <- - actionGroupAddRadioActionsAndGetConnID agr viewmods 0 (assignViewMode evar) -- const (return ()))+ actionGroupAddRadioActionsAndGetConnID agr viewmods 0 (assignViewMode evar) _mpointconnid <- actionGroupAddRadioActionsAndGetConnID agr pointmods 0 (assignPoint evar) mpenmodconnid <- actionGroupAddRadioActionsAndGetConnID agr penmods 0 (assignPenMode evar)- _mcolorconnid <- + mcolorconnid <- actionGroupAddRadioActionsAndGetConnID agr colormods 0 (assignColor evar) - actionGroupAddRadioActions agr bkgstyles 2 (assignBkgStyle evar)- + _mbkgstyconnid <-+ actionGroupAddRadioActionsAndGetConnID agr bkgstyles 2 (assignBkgStyle evar)+ mnpgmodconnid <- + actionGroupAddRadioActionsAndGetConnID agr newpagemods 0 (assignNewPageMode evar)+ let disabledActions = [ recenta, printa , cuta, copya, deletea , setzma- {- , shwlayera, hidlayera -} , newpgea, ppsizea, ppclra , defppa, setdefppa- -- , shpreca, rulera , erasropta, hiltropta, txtfnta, defpena, defersra, defhiltra, deftxta , setdefopta- , dcrdcorea, ersrtipa, pghilta, mltpgvwa- , mltpga, btn2mapa, btn3mapa, antialiasbmpa, prgrsbkga, prntpprulea - , lfthndscrbra, shrtnmenua, autosaveprefa, saveprefa - , abouta + , abouta , defaulta +#ifndef DYRE+ , relauncha+#endif+#ifndef HUB+ , editnetsrca+ , huba+#endif ] enabledActions = [ opena, savea, saveasa, reloada, versiona, showreva, showida, quita , pastea, fstpagea, prvpagea, nxtpagea, lstpagea , clra, penopta, zooma, nrmsizea, pgwdtha, texta + , newpagemoda ] --- mapM_ (\x->actionSetSensitive x True) enabledActions - mapM_ (\x->actionSetSensitive x False) disabledActions+ mapM_ (\x->Gtk.actionSetSensitive x True) enabledActions + mapM_ (\x->Gtk.actionSetSensitive x False) disabledActions -- -- -- radio actions --- ui <- uiManagerNew+ ui <- Gtk.uiManagerNew uiDecl <- readFile (resDir </> "menu.xml") - uiManagerAddUiFromString ui uiDecl- uiManagerInsertActionGroup ui agr 0 - Just ra2 <- actionGroupGetAction agr "PENFINEA"- Gtk.set (castToRadioAction ra2) [radioActionCurrentValue := 2]- Just ra3 <- actionGroupGetAction agr "SELREGNA"- actionSetSensitive ra3 True - Just ra4 <- actionGroupGetAction agr "VERTSPA"- actionSetSensitive ra4 True- -- Just ra5 <- actionGroupGetAction agr "HANDA"- -- actionSetSensitive ra5 False- Just ra6 <- actionGroupGetAction agr "CONTA"- actionSetSensitive ra6 True- Just _ra7 <- actionGroupGetAction agr "PENA"- actionSetSensitive ra6 True - Just toolbar1 <- uiManagerGetWidget ui "/ui/toolbar1"- toolbarSetStyle (castToToolbar toolbar1) ToolbarIcons - toolbarSetIconSize (castToToolbar toolbar1) IconSizeSmallToolbar- Just toolbar2 <- uiManagerGetWidget ui "/ui/toolbar2"- toolbarSetStyle (castToToolbar toolbar2) ToolbarIcons - toolbarSetIconSize (castToToolbar toolbar2) IconSizeSmallToolbar - - -- Just pendropdown <- uiManagerGetWidget ui "/ui/toolbar2/PENDROPDOWN"- - + Gtk.uiManagerAddUiFromString ui uiDecl+ Gtk.uiManagerInsertActionGroup ui agr 0 + Just ra2 <- Gtk.actionGroupGetAction agr ("PENFINEA" :: String)+ Gtk.set (Gtk.castToRadioAction ra2) [Gtk.radioActionCurrentValue Gtk.:= 2]+ Just ra3 <- Gtk.actionGroupGetAction agr ("SELREGNA" :: String)+ Gtk.actionSetSensitive ra3 True + Just ra4 <- Gtk.actionGroupGetAction agr ("VERTSPA" :: String)+ Gtk.actionSetSensitive ra4 True+ Just ra6 <- Gtk.actionGroupGetAction agr ("CONTA" :: String)+ Gtk.actionSetSensitive ra6 True+ Just _ra7 <- Gtk.actionGroupGetAction agr ("PENA" :: String)+ Gtk.actionSetSensitive ra6 True + Just toolbar1 <- Gtk.uiManagerGetWidget ui ("/ui/toolbar1" :: String)+ Gtk.toolbarSetStyle (Gtk.castToToolbar toolbar1) Gtk.ToolbarIcons +#ifndef GTK3+ Gtk.toolbarSetIconSize (Gtk.castToToolbar toolbar1) Gtk.IconSizeSmallToolbar+#endif + Just toolbar2 <- Gtk.uiManagerGetWidget ui ("/ui/toolbar2" :: String)+ Gtk.toolbarSetStyle (Gtk.castToToolbar toolbar2) Gtk.ToolbarIcons +#ifndef GTK3+ Gtk.toolbarSetIconSize (Gtk.castToToolbar toolbar2) Gtk.IconSizeSmallToolbar +#endif + let uicomponentsignalhandler = set penModeSignal mpenmodconnid . set pageModeSignal mpgmodconnid + . set penColorSignal mcolorconnid+ . set newPageModeSignal mnpgmodconnid $ defaultUIComponentSignalHandler return (ui,uicomponentsignalhandler) -- |-actionGroupAddRadioActionsAndGetConnID :: ActionGroup - -> [RadioActionEntry]+actionGroupAddRadioActionsAndGetConnID :: Gtk.ActionGroup + -> [Gtk.RadioActionEntry] -> Int - -> (RadioAction -> IO ()) - -> IO (Maybe (ConnectId RadioAction))+ -> (Gtk.RadioAction -> IO ()) + -> IO (Maybe (Gtk.ConnectId Gtk.RadioAction)) actionGroupAddRadioActionsAndGetConnID self entries _value onChange = do mgroup <- foldM - (\mgroup (n,RadioActionEntry name label stockId accelerator tooltip value) -> do- action <- radioActionNew name label tooltip stockId value- case mgroup of - Nothing -> return () - Just gr -> radioActionSetGroup action gr- when (n==value) (toggleActionSetActive action True)- actionGroupAddActionWithAccel self action accelerator+ (\mgroup (n,Gtk.RadioActionEntry name label stockId accelerator tooltip value) -> do+ action <- Gtk.radioActionNew name label tooltip stockId value+ F.forM_ mgroup $ \gr -> Gtk.radioActionSetGroup action gr+ when (n==value) (Gtk.toggleActionSetActive action True)+ Gtk.actionGroupAddActionWithAccel self action accelerator return (Just action)) Nothing (zip [0..] entries) case mgroup of Nothing -> return Nothing Just gr -> do - connid <- (gr `on` radioActionChanged) onChange+ connid <- (gr `Gtk.on` Gtk.radioActionChanged) onChange return (Just connid) -- | -assignViewMode :: EventVar -> RadioAction -> IO ()+assignViewMode :: EventVar -> Gtk.RadioAction -> IO () assignViewMode evar a = viewModeToUserEvent a >>= eventHandler evar . UsrEv -- | -assignPenMode :: EventVar -> RadioAction -> IO ()+assignPenMode :: EventVar -> Gtk.RadioAction -> IO () assignPenMode evar a = do - v <- radioActionGetCurrentValue a+ v <- Gtk.radioActionGetCurrentValue a eventHandler evar (UsrEv (AssignPenMode (int2PenType v))) -- | -assignColor :: EventVar -> RadioAction -> IO () +assignColor :: EventVar -> Gtk.RadioAction -> IO () assignColor evar a = do - v <- radioActionGetCurrentValue a+ v <- Gtk.radioActionGetCurrentValue a let c = int2Color v eventHandler evar (UsrEv (PenColorChanged c)) -- | -assignPoint :: EventVar -> RadioAction -> IO () +assignPoint :: EventVar -> Gtk.RadioAction -> IO () assignPoint evar a = do - v <- radioActionGetCurrentValue a+ v <- Gtk.radioActionGetCurrentValue a eventHandler evar (UsrEv (PenWidthChanged v)) -- | -assignBkgStyle :: EventVar -> RadioAction -> IO ()+assignBkgStyle :: EventVar -> Gtk.RadioAction -> IO () assignBkgStyle evar a = do - v <- radioActionGetCurrentValue a + v <- Gtk.radioActionGetCurrentValue a let sty = int2BkgStyle v eventHandler evar (UsrEv (BackgroundStyleChanged sty)) -- | +assignNewPageMode :: EventVar -> Gtk.RadioAction -> IO ()+assignNewPageMode evar a = do + v <- Gtk.radioActionGetCurrentValue a+ eventHandler evar (UsrEv (AssignNewPageMode (int2NewPageMode v)))+++-- | int2PenType :: Int -> Either PenType SelectType int2PenType 0 = Left PenWork int2PenType 1 = Left EraserWork@@ -656,3 +689,17 @@ int2BkgStyle 2 = BkgStyleRuled int2BkgStyle 3 = BkgStyleGraph int2BkgStyle _ = BkgStyleRuled +++-- | +int2NewPageMode :: Int -> NewPageModeType+int2NewPageMode 0 = NPPlain+int2NewPageMode 1 = NPLast+int2NewPageMode 2 = NPCycle+int2NewPageMode _ = error "No such new page mode"++-- |+newPageMode2Int :: NewPageModeType -> Int+newPageMode2Int NPPlain = 0+newPageMode2Int NPLast = 1+newPageMode2Int NPCycle = 2
src/Hoodle/GUI/Reflect.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-}@@ -7,7 +8,7 @@ -- Module : Hoodle.GUI.Reflect -- Copyright : (c) 2013, 2014 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -16,85 +17,85 @@ module Hoodle.GUI.Reflect where -import Control.Lens (view,Simple,Lens)-import Control.Monad (liftM, when)-import qualified Control.Monad.State as St-import Control.Monad.Trans +import Control.Lens (view, Simple,Lens, (^.), (.~), _1,_2,_3)+import Control.Monad.State as St import Data.Array.MArray-import Data.Foldable (forM_)+import qualified Data.Foldable as F (forM_,mapM_) import qualified Data.Map as M (lookup) import Data.Word-import Graphics.UI.Gtk hiding (get,set)-import qualified Graphics.UI.Gtk as Gtk (set)+import qualified Graphics.UI.Gtk as Gtk ---import Hoodle.GUI.Menu -import Hoodle.Coroutine.Draw-import Hoodle.Type.Canvas-import Hoodle.Type.Coroutine-import Hoodle.Type.Enum -import Hoodle.Type.Event-import Hoodle.Type.HoodleState-import Hoodle.Type.PageArrangement-import Hoodle.Type.Predefined -import Hoodle.Util -import Hoodle.View.Coordinate+import Hoodle.Accessor+import Hoodle.Coroutine.Draw+import Hoodle.GUI.Menu +import Hoodle.Type.Canvas+import Hoodle.Type.Coroutine+import Hoodle.Type.Enum +import Hoodle.Type.Event+import Hoodle.Type.HoodleState+import Hoodle.Type.PageArrangement+import Hoodle.Type.Predefined +import Hoodle.Util +import Hoodle.View.Coordinate -- -import Debug.Trace+-- import Debug.Trace -- | -changeCurrentCanvasId :: CanvasId -> MainCoroutine HoodleState +changeCurrentCanvasId :: CanvasId -> MainCoroutine UnitHoodle changeCurrentCanvasId cid = do - xstate1 <- St.get- maybe (return xstate1) - (\xst -> do St.put xst - return xst)- (setCurrentCanvasId cid xstate1)- reflectViewModeUI- St.get + xst <- St.get+ let uhdl = view (unitHoodles.currentUnit) xst+ case setCurrentCanvasId cid uhdl of+ Nothing -> return uhdl+ Just uhdl' -> do + pureUpdateUhdl (const uhdl')+ reflectViewModeUI+ return uhdl' + -- | check current canvas id and new active canvas id and invalidate if it's -- changed. chkCvsIdNInvalidate :: CanvasId -> MainCoroutine () chkCvsIdNInvalidate cid = do - currcid <- liftM (getCurrentCanvasId) St.get + currcid <- liftM (getCurrentCanvasId . view (unitHoodles.currentUnit) ) St.get when (currcid /= cid) (changeCurrentCanvasId cid >> invalidateAll) +-- | block signal for act+blockWhile :: (Gtk.GObjectClass w) => Maybe (Gtk.ConnectId w) -> IO () -> IO ()+blockWhile msig act = do+ F.mapM_ (\_ -> print "signal will be blocked") msig+ F.mapM_ Gtk.signalBlock msig >> act >> F.mapM_ Gtk.signalUnblock msig -blockWhile :: (GObjectClass w) => Maybe (ConnectId w) -> IO () -> IO ()-blockWhile msig act = - maybe (return ()) signalBlock msig- >> act - >> maybe (return ()) signalUnblock msig- -- | reflect view mode UI for current canvas info reflectViewModeUI :: MainCoroutine () reflectViewModeUI = do xstate <- St.get- let cinfobox = view currentCanvasInfo xstate - ui = view gtkUIManager xstate + let uhdl = view (unitHoodles.currentUnit) xstate+ cinfobox = view currentCanvasInfo uhdl+ ui = view gtkUIManager xstate let mconnid = view (uiComponentSignalHandler.pageModeSignal) xstate- agr <- liftIO $ uiManagerGetActionGroups ui+ agr <- liftIO $ Gtk.uiManagerGetActionGroups ui ra1 <- maybe (error "reflectUI") return =<< - liftIO (actionGroupGetAction (head agr) "ONEPAGEA")- let wra1 = castToRadioAction ra1 + liftIO (Gtk.actionGroupGetAction (head agr) "ONEPAGEA")+ let wra1 = Gtk.castToRadioAction ra1 unboxBiAct (pgmodupdate_s mconnid wra1) (pgmodupdate_c mconnid wra1) cinfobox return () where pgmodupdate_s mconnid wra1 _cinfo = do liftIO $ blockWhile mconnid $- Gtk.set wra1 [radioActionCurrentValue := 1 ] + Gtk.set wra1 [Gtk.radioActionCurrentValue Gtk.:= 1 ] pgmodupdate_c mconnid wra1 _cinfo = do liftIO $ blockWhile mconnid $ - Gtk.set wra1 [radioActionCurrentValue := 0 ] + Gtk.set wra1 [Gtk.radioActionCurrentValue Gtk.:= 0 ] -- | reflectPenModeUI :: MainCoroutine () reflectPenModeUI = do - reflectUIComponent penModeSignal "PENA" f- reflectCursor+ reflectUIRadio penModeSignal "PENA" f+ reflectCursor False where f xst = Just $- hoodleModeStateEither (view hoodleModeState xst) # + hoodleModeStateEither ((view hoodleModeState . view (unitHoodles.currentUnit)) xst) # either (\_ -> (penType2Int. Left .view (penInfo.penType)) xst) (\_ -> (penType2Int. Right .view (selectInfo.selectType)) xst) @@ -102,8 +103,8 @@ -- | reflectPenColorUI :: MainCoroutine () reflectPenColorUI = do - reflectUIComponent penColorSignal "BLUEA" f- reflectCursor+ reflectUIRadio penColorSignal "BLUEA" f+ reflectCursor False where f xst = let mcolor = @@ -117,8 +118,8 @@ -- | reflectPenWidthUI :: MainCoroutine () reflectPenWidthUI = do - reflectUIComponent penPointSignal "PENVERYFINEA" f- reflectCursor+ reflectUIRadio penPointSignal "PENVERYFINEA" f+ reflectCursor False where f xst = case view (penInfo.penType) xst of @@ -127,103 +128,125 @@ HighlighterWork -> let x = (Just . point2Int HighlighterWork . view (penInfo.penSet.currHighlighter.penWidth)) xst- y = view (penInfo.penSet.currHighlighter.penWidth) xst- in trace (" x= " ++ show x ++ " y = " ++ show y ) x + -- y = view (penInfo.penSet.currHighlighter.penWidth) xst+ in x EraserWork -> (Just . point2Int EraserWork . view (penInfo.penSet.currEraser.penWidth)) xst _ -> Nothing +-- |+reflectNewPageModeUI :: MainCoroutine ()+reflectNewPageModeUI = + reflectUIRadio newPageModeSignal "NEWPAGEPLAINA" (Just . newPageMode2Int . (^. settings.newPageMode))+ -- | -reflectUIComponent :: Simple Lens UIComponentSignalHandler (Maybe (ConnectId RadioAction))- -> String - -> (HoodleState -> Maybe Int) - -> MainCoroutine ()-reflectUIComponent lnz name f = do +reflectUIRadio :: Simple Lens UIComponentSignalHandler (Maybe (Gtk.ConnectId Gtk.RadioAction))+ -> String + -> (HoodleState -> Maybe Int) + -> MainCoroutine ()+reflectUIRadio lnz name f = do xst <- St.get let ui = view gtkUIManager xst mconnid = view (uiComponentSignalHandler.lnz) xst - agr <- liftIO $ uiManagerGetActionGroups ui - Just pma <- liftIO $ actionGroupGetAction (head agr) name - let wpma = castToRadioAction pma + agr <- liftIO $ Gtk.uiManagerGetActionGroups ui + Just pma <- liftIO $ Gtk.actionGroupGetAction (head agr) name + let wpma = Gtk.castToRadioAction pma update xst wpma mconnid where update xst wpma mconnid = do (f xst) # - (maybe (return ()) $ \v -> do- doIOaction $ \_evhandler -> do - blockWhile mconnid - (Gtk.set wpma [radioActionCurrentValue := v ] )- return (UsrEv ActionOrdered)- go)- where go = do r <- nextevent- case r of- ActionOrdered -> return ()- _ -> go + (maybe (return ()) $ \v ->+ doIOaction_ $ blockWhile mconnid (Gtk.set wpma [Gtk.radioActionCurrentValue Gtk.:= v ] )+ ) ++-- | this function must be moved to GUI.Reflect+reflectUIToggle :: Gtk.UIManager -> String -> Bool -> IO ()+reflectUIToggle ui str b = do + agr <- Gtk.uiManagerGetActionGroups ui >>= \x -> + case x of+ [] -> error "No action group?"+ y:_ -> return y+ Just savea <- Gtk.actionGroupGetAction agr str -- ("SAVEA" :: String)+ Gtk.actionSetSensitive savea b+ -- | -reflectCursor :: MainCoroutine () -reflectCursor = do +reflectCursor :: Bool -> MainCoroutine () +reflectCursor isforced = do xst <- St.get - let useVCursor = view (settings.doesUseVariableCursor) xst - let go = do r <- nextevent - case r of- ActionOrdered -> return ()- _ -> go - if useVCursor - then - act xst >> go - else do - doIOaction $ \_ -> do- let cinfobox = view currentCanvasInfo xst - canvas = forBoth' unboxBiAct (view drawArea) cinfobox - win <- widgetGetDrawWindow canvas- postGUIAsync (drawWindowSetCursor win Nothing) - return (UsrEv ActionOrdered)- go - where act xst = doIOaction $ \_ -> do - let -- mcur = view cursorInfo xst - cinfobox = view currentCanvasInfo xst - canvas = forBoth' unboxBiAct (view drawArea) cinfobox - cpn = PageNum $ - forBoth' unboxBiAct (view currentPageNum) cinfobox- pinfo = view penInfo xst - pcolor = view (penSet . currPen . penColor) pinfo- pwidth = view (penSet . currPen . penWidth) pinfo - win <- widgetGetDrawWindow canvas- dpy <- widgetGetDisplay canvas - - geometry <- - forBoth' unboxBiAct (\c -> let arr = view (viewInfo.pageArrangement) c- in makeCanvasGeometry cpn arr canvas- ) cinfobox- let p2c = desktop2Canvas geometry . page2Desktop geometry- CvsCoord (x0,_y0) = p2c (cpn, PageCoord (0,0)) - CvsCoord (x1,_y1) = p2c (cpn, PageCoord (pwidth,pwidth))- cursize = (x1-x0) - (r,g,b,a) = case pcolor of - ColorRGBA r' g' b' a' -> (r',g',b',a')- _ -> maybe (0,0,0,1) id (M.lookup pcolor penColorRGBAmap)- pb <- pixbufNew ColorspaceRgb True 8 maxCursorWidth maxCursorHeight - let numPixels = maxCursorWidth*maxCursorHeight- pbData <- (pixbufGetPixels pb :: IO (PixbufData Int Word8))- forM_ [0..numPixels-1] $ \i -> do - let cvt :: Double -> Word8- cvt x | x < 0.0039 = 0- | x > 0.996 = 255- | otherwise = fromIntegral (floor (x*256-1) `mod` 256 :: Int)- if (fromIntegral (i `mod` maxCursorWidth)) < cursize - && (fromIntegral (i `div` maxCursorWidth)) < cursize - then do - writeArray pbData (4*i) (cvt r)- writeArray pbData (4*i+1) (cvt g) - writeArray pbData (4*i+2) (cvt b)- writeArray pbData (4*i+3) (cvt a)- else do- writeArray pbData (4*i) 0- writeArray pbData (4*i+1) 0- writeArray pbData (4*i+2) 0- writeArray pbData (4*i+3) 0- - postGUIAsync . drawWindowSetCursor win . Just =<< - cursorNewFromPixbuf dpy pb - (floor cursize `div` 2) (floor cursize `div` 2)- return (UsrEv ActionOrdered)+ let b = view (settings.doesUseVariableCursor) xst+ pinfo = view penInfo xst + pcolor = view (penSet . currPen . penColor) pinfo+ pwidth = view (penSet . currPen . penWidth) pinfo + cinfo = view cursorInfo xst+ (ccolor,cwidth,cvar) = cinfo+ when (pcolor /= ccolor || pwidth /= cwidth || b /= cvar || isforced) $ do+ msgShout "reflectCursor: change cursor"+ put . (cursorInfo._1 .~ pcolor) . (cursorInfo._2 .~ pwidth) . (cursorInfo._3 .~ b) $ xst + doIOaction_ $ if b + then varyCursor xst + else do let uhdl = view (unitHoodles.currentUnit) xst+ cinfobox = view currentCanvasInfo uhdl + canvas = forBoth' unboxBiAct (view drawArea) cinfobox+#ifdef GTK3+ Just win <- Gtk.widgetGetWindow canvas+#else+ win <- Gtk.widgetGetDrawWindow canvas+#endif+ Gtk.postGUIAsync (Gtk.drawWindowSetCursor win Nothing) + return (UsrEv ActionOrdered)+ where + varyCursor xst = do + putStrLn "reflectCursor : inside act"++ -- Gtk.postGUIAsync $ do + let uhdl = view (unitHoodles.currentUnit) xst+ -- mcur = view cursorInfo xst + cinfobox = view currentCanvasInfo uhdl+ canvas = forBoth' unboxBiAct (view drawArea) cinfobox + cpn = PageNum $ + forBoth' unboxBiAct (view currentPageNum) cinfobox+ pinfo = view penInfo xst + pcolor = view (penSet . currPen . penColor) pinfo+ pwidth = view (penSet . currPen . penWidth) pinfo +#ifdef GTK3+ Just win <- Gtk.widgetGetWindow canvas+#else+ win <- Gtk.widgetGetDrawWindow canvas+#endif+ dpy <- Gtk.widgetGetDisplay canvas ++ geometry <- + forBoth' unboxBiAct (\c -> let arr = view (viewInfo.pageArrangement) c+ in makeCanvasGeometry cpn arr canvas+ ) cinfobox+ let p2c = desktop2Canvas geometry . page2Desktop geometry+ CvsCoord (x0,_y0) = p2c (cpn, PageCoord (0,0)) + CvsCoord (x1,_y1) = p2c (cpn, PageCoord (pwidth,pwidth))+ cursize = (x1-x0) + (r,g,b,a) = case pcolor of + ColorRGBA r' g' b' a' -> (r',g',b',a')+ _ -> maybe (0,0,0,1) id (M.lookup pcolor penColorRGBAmap)+ pb <- Gtk.pixbufNew Gtk.ColorspaceRgb True 8 maxCursorWidth maxCursorHeight + let numPixels = maxCursorWidth*maxCursorHeight+ pbData <- (Gtk.pixbufGetPixels pb :: IO (Gtk.PixbufData Int Word8))+ F.forM_ [0..numPixels-1] $ \i -> do + let cvt :: Double -> Word8+ cvt x | x < 0.0039 = 0+ | x > 0.996 = 255+ | otherwise = fromIntegral (floor (x*256-1) `mod` 256 :: Int)+ if (fromIntegral (i `mod` maxCursorWidth)) < cursize + && (fromIntegral (i `div` maxCursorWidth)) < cursize + then do + writeArray pbData (4*i) (cvt r)+ writeArray pbData (4*i+1) (cvt g) + writeArray pbData (4*i+2) (cvt b)+ writeArray pbData (4*i+3) (cvt a)+ else do+ writeArray pbData (4*i) 0+ writeArray pbData (4*i+1) 0+ writeArray pbData (4*i+2) 0+ writeArray pbData (4*i+3) 0++ Gtk.drawWindowSetCursor win . Just =<< + Gtk.cursorNewFromPixbuf dpy pb (floor cursize `div` 2) (floor cursize `div` 2)+ return (UsrEv ActionOrdered)
src/Hoodle/ModelAction/Adjustment.hs view
@@ -1,7 +1,7 @@ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.ModelAction.Adjustment --- Copyright : (c) 2011, 2012 Ian-Woo Kim+-- Copyright : (c) 2011,2012,2014 Ian-Woo Kim -- -- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>@@ -13,7 +13,8 @@ module Hoodle.ModelAction.Adjustment where -- from other package-import Graphics.UI.Gtk +import qualified Data.Foldable as F (mapM_)+import qualified Graphics.UI.Gtk as Gtk -- from hoodle-platform import Data.Hoodle.BBox (BBox(..)) import Data.Hoodle.Simple (Dimension(..))@@ -24,31 +25,30 @@ -- | adjust values, upper limit and page size according to canvas geometry adjustScrollbarWithGeometry :: CanvasGeometry - -> ((Adjustment,Maybe (ConnectId Adjustment))- ,(Adjustment,Maybe (ConnectId Adjustment))) + -> ((Gtk.Adjustment,Maybe (Gtk.ConnectId Gtk.Adjustment))+ ,(Gtk.Adjustment,Maybe (Gtk.ConnectId Gtk.Adjustment))) -> IO () adjustScrollbarWithGeometry geometry ((hadj,mconnidh),(vadj,mconnidv)) = do let DesktopDimension (Dim w h) = desktopDim geometry ViewPortBBox (BBox (x0,y0) (x1,y1)) = canvasViewPort geometry xsize = x1-x0 ysize = y1-y0 - maybe (return ()) signalBlock mconnidh- maybe (return ()) signalBlock mconnidv- adjustmentSetUpper hadj w - adjustmentSetUpper vadj h - adjustmentSetValue hadj x0 - adjustmentSetValue vadj y0- adjustmentSetPageSize hadj xsize -- (min xsize w)- adjustmentSetPageSize vadj ysize -- (min ysize h)- adjustmentSetPageIncrement hadj (xsize*0.9)- adjustmentSetPageIncrement vadj (ysize*0.9)- maybe (return ()) signalUnblock mconnidh- maybe (return ()) signalUnblock mconnidv+ F.mapM_ Gtk.signalBlock mconnidh+ F.mapM_ Gtk.signalBlock mconnidv+ Gtk.adjustmentSetUpper hadj w + Gtk.adjustmentSetUpper vadj h + Gtk.adjustmentSetValue hadj x0 + Gtk.adjustmentSetValue vadj y0+ Gtk.adjustmentSetPageSize hadj xsize -- (min xsize w)+ Gtk.adjustmentSetPageSize vadj ysize -- (min ysize h)+ Gtk.adjustmentSetPageIncrement hadj (xsize*0.9)+ Gtk.adjustmentSetPageIncrement vadj (ysize*0.9)+ F.mapM_ Gtk.signalUnblock mconnidh+ F.mapM_ Gtk.signalUnblock mconnidv -- | --setAdjustments :: ((Adjustment,Maybe (ConnectId Adjustment))- ,(Adjustment,Maybe (ConnectId Adjustment))) +setAdjustments :: ((Gtk.Adjustment,Maybe (Gtk.ConnectId Gtk.Adjustment))+ ,(Gtk.Adjustment,Maybe (Gtk.ConnectId Gtk.Adjustment))) -> (Double,Double) -> (Double,Double) -> (Double,Double) @@ -57,18 +57,18 @@ setAdjustments ((hadj,mconnidh),(vadj,mconnidv)) (upperx,uppery) (lowerx,lowery) (valuex,valuey) (pagex,pagey) = do - maybe (return ()) signalBlock mconnidh- maybe (return ()) signalBlock mconnidv- adjustmentSetUpper hadj upperx - adjustmentSetUpper vadj uppery - adjustmentSetLower hadj lowerx- adjustmentSetLower vadj lowery- adjustmentSetValue hadj valuex- adjustmentSetValue vadj valuey - adjustmentSetPageSize hadj pagex- adjustmentSetPageSize vadj pagey- maybe (return ()) signalUnblock mconnidh- maybe (return ()) signalUnblock mconnidv+ F.mapM_ Gtk.signalBlock mconnidh+ F.mapM_ Gtk.signalBlock mconnidv+ Gtk.adjustmentSetUpper hadj upperx + Gtk.adjustmentSetUpper vadj uppery + Gtk.adjustmentSetLower hadj lowerx+ Gtk.adjustmentSetLower vadj lowery+ Gtk.adjustmentSetValue hadj valuex+ Gtk.adjustmentSetValue vadj valuey + Gtk.adjustmentSetPageSize hadj pagex+ Gtk.adjustmentSetPageSize vadj pagey+ F.mapM_ Gtk.signalUnblock mconnidh+ F.mapM_ Gtk.signalUnblock mconnidv
src/Hoodle/ModelAction/Clipboard.hs view
@@ -20,7 +20,7 @@ import qualified Data.ByteString.Base64 as B64 import qualified Data.ByteString.Char8 as C8 import qualified Data.Serialize as Se -import Graphics.UI.Gtk hiding (get,set)+import qualified Graphics.UI.Gtk as Gtk -- from hoodle-platform import Data.Hoodle.Simple -- import Graphics.Hoodle.Render.Type@@ -37,12 +37,10 @@ | null itms = return xstate | otherwise = do let ui = view gtkUIManager xstate- hdltag <- atomNew "hoodle"- -- tgttag <- atomNew "Stroke"- -- seltag <- atomNew "Stroke"- clipbd <- clipboardGet hdltag+ hdltag <- Gtk.atomNew "hoodle"+ clipbd <- Gtk.clipboardGet hdltag let bstr = C8.unpack . B64.encode . Se.encode $ itms - clipboardSetText clipbd bstr+ Gtk.clipboardSetText clipbd bstr togglePaste ui True case (view hookSet xstate) of Nothing -> return ()
src/Hoodle/ModelAction/ContextMenu.hs view
@@ -1,11 +1,13 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-} ----------------------------------------------------------------------------- -- | -- Module : Hoodle.ModelAction.ContextMenu--- Copyright : (c) 2011-2014 Ian-Woo Kim+-- Copyright : (c) 2011-2015 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -14,17 +16,20 @@ module Hoodle.ModelAction.ContextMenu where -import Control.Concurrent (forkIO, threadDelay) import qualified Data.ByteString.Char8 as B-import Data.Foldable (forM_) import Data.UUID.V4-import DBus -import DBus.Client import qualified Graphics.Rendering.Cairo as Cairo-import Graphics.UI.Gtk+import qualified Graphics.UI.Gtk as Gtk import System.Directory import System.FilePath +#ifdef HUB+import Control.Concurrent (forkIO, threadDelay)+import Control.Exception+import Data.Foldable (forM_)+import DBus +import DBus.Client import System.Process+#endif -- import Data.Hoodle.BBox import Data.Hoodle.Simple@@ -35,56 +40,58 @@ import Hoodle.Util -- |-menuOpenALink :: UrlPath -> IO MenuItem-menuOpenALink urlpath = do +menuOpenALink :: (AllEvent -> IO ()) -> UrlPath -> IO Gtk.MenuItem+menuOpenALink evhandler urlpath = do let urlname = case urlpath of FileUrl fp -> fp HttpUrl url -> url - menuitemlnk <- menuItemNewWithLabel ("Open "++urlname) - menuitemlnk `on` menuItemActivate $ openLinkAction urlpath Nothing+ menuitemlnk <- Gtk.menuItemNewWithLabel ("Open "++urlname :: String) + menuitemlnk `Gtk.on` Gtk.menuItemActivate $ evhandler (UsrEv (OpenLink urlpath Nothing)) return menuitemlnk - -- | -openLinkAction :: UrlPath +#ifdef HUB+openLinkActionDBus :: UrlPath -> Maybe (B.ByteString,B.ByteString) -- ^ (docid,anchorid) -> IO () -openLinkAction urlpath mid = do- cli <- connectSession- case urlpath of - FileUrl fp -> do - putStrLn "test dbus"- emit cli (signal "/" "org.ianwookim.hoodle" "findWindow") - { signalBody = [ toVariant fp] } - return () - HttpUrl url -> do - let cmdargs = [url]- createProcess (proc "xdg-open" cmdargs) - return () - forkIO $ do - threadDelay 2000000- forM_ mid $ \(docid,anchorid) -> do- print (docid,anchorid)- emit cli (signal "/" "org.ianwookim.hoodle" "callLink")- { signalBody = - [ toVariant (B.unpack docid - ++ "," - ++ B.unpack anchorid) ] }- return ()+openLinkActionDBus urlpath mid = do+ flip catch (\(ex :: SomeException) -> print ex ) $ do+ cli <- connectSession+ case urlpath of + FileUrl fp -> do + emit cli (signal "/" "org.ianwookim.hoodle" "findWindow") { signalBody = [ toVariant fp] } + return () + HttpUrl url -> do + let cmdargs = [url]+ createProcess (proc "xdg-open" cmdargs) + return () + forkIO $ do + threadDelay 2000000+ forM_ mid $ \(docid,anchorid) -> do+ print (docid,anchorid)+ emit cli (signal "/" "org.ianwookim.hoodle" "callLink")+ { signalBody = + [ toVariant (B.unpack docid + ++ "," + ++ B.unpack anchorid) ] }+ return ()+#endif++ -- | -menuCreateALink :: (AllEvent -> IO ()) -> [RItem] -> IO (Maybe MenuItem)+menuCreateALink :: (AllEvent -> IO ()) -> [RItem] -> IO (Maybe Gtk.MenuItem) menuCreateALink evhandler sitems = if (length . filter isLinkInRItem) sitems > 0 then return Nothing - else do mi <- menuItemNewWithLabel "Create a link to..." - mi `on` menuItemActivate $ + else do mi <- Gtk.menuItemNewWithLabel ("Create a link to..." :: String)+ mi `Gtk.on` Gtk.menuItemActivate $ evhandler (UsrEv (GotContextMenuSignal CMenuCreateALink)) return (Just mi) -- |-makeSVGFromSelection :: RenderCache -> [RItem] -> BBox -> IO SVG -makeSVGFromSelection cache hititms (BBox (ulx,uly) (lrx,lry)) = do +makeSVGFromSelection :: RenderCache -> CanvasId -> [RItem] -> BBox -> IO SVG +makeSVGFromSelection cache cid hititms (BBox (ulx,uly) (lrx,lry)) = do uuid <- nextRandom tdir <- getTemporaryDirectory let filename = tdir </> show uuid <.> "svg"@@ -92,7 +99,7 @@ (w,h) = (lrx-ulx,lry-uly) Cairo.withSVGSurface filename w h $ \s -> Cairo.renderWith s $ do Cairo.translate (-ulx) (-uly) - mapM_ (renderRItem cache) hititms + mapM_ (renderRItem cache cid) hititms bstr <- B.readFile filename let svg = SVG Nothing Nothing bstr (x,y) (Dim w h) svg `seq` removeFile filename
src/Hoodle/ModelAction/File.hs view
@@ -5,9 +5,9 @@ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.ModelAction.File --- Copyright : (c) 2011-2014 Ian-Woo Kim+-- Copyright : (c) 2011-2015 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -19,16 +19,15 @@ -- from other package import Control.Applicative import Control.Lens (view,set)-import Data.Attoparsec +import Data.Attoparsec.ByteString.Char8 import Data.ByteString.Base64 import qualified Data.ByteString.Char8 as C import qualified Data.ByteString.Lazy.Char8 as L-import qualified Data.IntMap as IM import Data.Maybe import Data.Monoid ((<>)) import Data.Time.Clock+import qualified Data.Traversable as T import Graphics.GD.ByteString -import Graphics.UI.Gtk hiding (get,set) import qualified Graphics.UI.Gtk.Poppler.Document as Poppler import qualified Graphics.UI.Gtk.Poppler.Page as PopplerPage import System.Directory (canonicalizePath)@@ -36,14 +35,14 @@ import System.IO (hClose, hFileSize, openFile, IOMode(..)) import System.Process -- from hoodle-platform -import Data.Hoodle.Generic import Data.Hoodle.Simple import Graphics.Hoodle.Render.Background-import Graphics.Hoodle.Render.Type.Background import Graphics.Hoodle.Render.Type.Hoodle import Text.Hoodle.Builder (builder) import qualified Text.Hoodle.Parse.Attoparsec as PA-import qualified Text.Hoodle.Migrate.V0_1_1_to_V0_2 as MV+import qualified Text.Hoodle.Migrate.V0_2_2_to_V0_3 as MV+-- import qualified Data.Hoodle.Simple.V0_3 as V0_3+import qualified Text.Hoodle.Migrate.V0_3_to_HEAD as MVHEAD -- from this package import Hoodle.Type.HoodleState import Hoodle.Util@@ -54,33 +53,56 @@ case parseOnly PA.checkHoodleVersion bstr of Left str -> error str Right v -> do - if ( v <= "0.1.1" ) - then MV.migrate bstr+ if ( v <= "0.2.2" ) + then T.traverse MVHEAD.hoodle2Hoodle =<< (MV.migrate bstr) else return (parseOnly PA.hoodle bstr) -- | this is very temporary, need to be changed. -findFirstPDFFile :: [(Int,RPage)] -> Maybe C.ByteString-findFirstPDFFile xs = let ys = (filter isJust . map f) xs - in if null ys then Nothing else head ys - where f (_,p) = case view gbackground p of - RBkgPDF _ fi _ _ _ -> Just fi- _ -> Nothing +findFirstPDFFile :: [Page] -> Maybe C.ByteString+findFirstPDFFile xs = let ys = mapMaybe f xs + in listToMaybe ys+ where f :: Page -> Maybe C.ByteString+ f p = case page_bkg p of+ BackgroundPdf _ _ fi _ -> fi+ _ -> Nothing+ -findAllPDFPages :: [(Int,RPage)] -> [Int]+findAllPDFPages :: [Page] -> [Int] findAllPDFPages = catMaybes . map f- where f (n,p) = case view gbackground p of - RBkgPDF _ _ _ _ _ -> Just n- _ -> Nothing + where f p = case page_bkg p of + BackgroundPdf _ _ _ n -> Just n+ _ -> Nothing -replacePDFPages :: [(Int,RPage)] -> [(Int,RPage)] +replacePDFPages :: [Page] -> [Page] replacePDFPages xs = map f xs - where f (n,p) = case view gbackground p of - RBkgPDF _ _ pdfn mpdf msfc -> (n, set gbackground (RBkgEmbedPDF pdfn mpdf msfc) p)- _ -> (n,p) + where f p = let bkg = page_bkg p+ in case bkg of + BackgroundPdf typ _ _ pdfn -> p { page_bkg = BackgroundEmbedPdf typ pdfn }+ _ -> p -- | -embedPDFInHoodle :: RHoodle -> IO RHoodle-embedPDFInHoodle hdl = do +embedPDFInHoodle :: Hoodle -> IO Hoodle -- RHoodle -> IO RHoodle+embedPDFInHoodle hdl = putStrLn "embedPDFInHoodle is now bugful. I do not do anything here " >> return hdl+{- let pgsWnum = zip [0..] (hoodle_pages hdl)+ mfn = findFirstPDFFile (hoodle_pages hdl)+ allpdfpg = findAllPDFPages pgs + case mfn of + Nothing -> return hdl + Just fn -> do + let fnstr = C.unpack fn + pglst = map show allpdfpg + cmdargs = [fnstr, "cat"] ++ pglst ++ ["output", "-"]+ -- print cmdargs + (_,Just hout,_,_) <- createProcess (proc "pdftk" cmdargs) { std_out = CreatePipe } + bstr <- C.hGetContents hout+ let ebdsrc = makeEmbeddedPdfSrcString bstr + npgs = (IM.fromAscList . replacePDFPages pgs + + nhdl0 = rHoodle2Hoodle . (gpages .~ npgs) $ hdl+ nhdl1 = nhdl0 { hoodle_embeddedpdf = Just ebdsrc }+ cnstrctRHoodle nhdl1+-}+{- let pgs = (IM.toAscList . view gpages) hdl mfn = findFirstPDFFile pgs allpdfpg = findAllPDFPages pgs @@ -97,7 +119,7 @@ let ebdsrc = makeEmbeddedPdfSrcString bstr npgs = (IM.fromAscList . replacePDFPages) pgs (return . set gembeddedpdf (Just ebdsrc) . set gpages npgs) hdl-+-} makeEmbeddedPdfSrcString :: C.ByteString -> C.ByteString @@ -172,27 +194,18 @@ -- | -saveHoodle :: HoodleState -> IO HoodleState -saveHoodle xstate = do - let hdl = (rHoodle2Hoodle . getHoodle) xstate - case view (hoodleFileControl.hoodleFileName) xstate of - Nothing -> return xstate - Just filename -> do - L.writeFile filename . builder $ hdl- ctime <- getCurrentTime - let ui = view gtkUIManager xstate- toggleSave ui False- return (set isSaved True . set (hoodleFileControl.lastSavedTime) (Just ctime) $ xstate )- --- | this function must be moved to GUI.Reflect-toggleSave :: UIManager -> Bool -> IO ()-toggleSave ui b = do - agr <- uiManagerGetActionGroups ui >>= \x -> - case x of- [] -> error "No action group?"- y:_ -> return y- Just savea <- actionGroupGetAction agr "SAVEA"- actionSetSensitive savea b+saveHoodle :: UnitHoodle -> IO UnitHoodle+saveHoodle uhdl = do + let hdl = (rHoodle2Hoodle . getHoodle) uhdl + case view (hoodleFileControl.hoodleFileName) uhdl of + LocalDir Nothing -> return uhdl + LocalDir (Just filename) -> action hdl filename + TempDir filename -> action hdl filename + where + action hdl filename = do + L.writeFile filename . builder $ hdl+ ctime <- getCurrentTime + return (set isSaved True . set (hoodleFileControl.lastSavedTime) (Just ctime) $ uhdl) -- | makeNewItemImage :: Bool -- ^ isEmbedded?@@ -216,7 +229,6 @@ (fromIntegral h * 72 / 90) | w >= h = Dim 300 (fromIntegral h*300/fromIntegral w) | otherwise = Dim (fromIntegral w*300/fromIntegral h) 300 - -- bstr <- savePngByteString img bstr <- C.readFile filename let b64str = encode bstr ebdsrc = "data:image/png;base64," <> b64str
src/Hoodle/ModelAction/Layer.hs view
@@ -1,7 +1,9 @@+{-# LANGUAGE CPP #-}+ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.ModelAction.Layer --- Copyright : (c) 2011-2013 Ian-Woo Kim+-- Copyright : (c) 2011-2014 Ian-Woo Kim -- -- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>@@ -16,8 +18,7 @@ import Control.Category import Control.Lens (view,over) import Data.IORef-import Graphics.UI.Gtk hiding (get,set)-import qualified Graphics.UI.Gtk as Gtk (get)+import qualified Graphics.UI.Gtk as Gtk -- from hoodle-platform import Data.Hoodle.Generic import Data.Hoodle.Zipper@@ -41,23 +42,28 @@ -- | -layerChooseDialog :: IORef Int -> Int -> Int -> IO Dialog+layerChooseDialog :: IORef Int -> Int -> Int -> IO Gtk.Dialog layerChooseDialog layernumref cidx len = do - dialog <- dialogNew - layerentry <- entryNew- entrySetText layerentry (show (succ cidx))- label <- labelNew (Just (" / " ++ show len))- hbox <- hBoxNew False 0 - upper <- dialogGetUpper dialog- boxPackStart upper hbox PackNatural 0 - boxPackStart hbox layerentry PackNatural 0 - boxPackStart hbox label PackGrow 0 - widgetShowAll upper- buttonOk <- dialogAddButton dialog stockOk ResponseOk- _buttonCancel <- dialogAddButton dialog stockCancel ResponseCancel+ dialog <- Gtk.dialogNew + layerentry <- Gtk.entryNew+ Gtk.entrySetText layerentry (show (succ cidx))+ label <- Gtk.labelNew (Just (" / " ++ show len))+ hbox <- Gtk.hBoxNew False 0 +#ifdef GTK3 + upper <- fmap Gtk.castToContainer (Gtk.dialogGetContentArea dialog)+ Gtk.containerAdd upper hbox+#else+ upper <- Gtk.dialogGetUpper dialog+ Gtk.boxPackStart upper hbox Gtk.PackNatural 0 +#endif+ Gtk.boxPackStart hbox layerentry Gtk.PackNatural 0 + Gtk.boxPackStart hbox label Gtk.PackGrow 0 + Gtk.widgetShowAll upper+ buttonOk <- Gtk.dialogAddButton dialog Gtk.stockOk Gtk.ResponseOk+ _buttonCancel <- Gtk.dialogAddButton dialog Gtk.stockCancel Gtk.ResponseCancel - buttonOk `on` buttonActivated $ do - txt <- Gtk.get layerentry entryText+ buttonOk `Gtk.on` Gtk.buttonActivated $ do + txt <- Gtk.get layerentry Gtk.entryText maybe (return ()) (modifyIORef layernumref . const . pred) . maybeRead $ txt return dialog
src/Hoodle/ModelAction/Page.hs view
@@ -4,9 +4,9 @@ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.ModelAction.Page --- Copyright : (c) 2011-2014 Ian-Woo Kim+-- Copyright : (c) 2011-2015 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -21,12 +21,10 @@ import Data.Functor.Identity (Identity(..)) import qualified Data.IntMap as M import Data.Traversable (mapM)-import Graphics.UI.Gtk (adjustmentGetValue)+import qualified Graphics.UI.Gtk as Gtk (adjustmentGetValue) -- from hoodle-platform import Data.Hoodle.Generic import Data.Hoodle.Select--- import Data.Hoodle.Zipper --- import Graphics.Hoodle.Render.Type -- from this package import Hoodle.Util import Hoodle.Type.Alias@@ -52,13 +50,13 @@ . hoodleModeStateEither -- |-updatePageAll :: HoodleModeState -> HoodleState -> IO HoodleState-updatePageAll hdlmodst xstate = do - let cmap = getCanvasInfoMap xstate+updatePageAll :: HoodleModeState -> UnitHoodle -> IO UnitHoodle+updatePageAll hdlmodst uhdl = do + let cmap = view cvsInfoMap uhdl cmap' <- mapM (updatePage hdlmodst . adjustPage hdlmodst) cmap- return $ maybe xstate id + return $ maybe uhdl id . setCanvasInfoMap cmap' - . set hoodleModeState hdlmodst $ xstate+ . set hoodleModeState hdlmodst $ uhdl -- | adjustPage :: HoodleModeState -> CanvasInfoBox -> CanvasInfoBox @@ -94,7 +92,7 @@ pg = getPageFromGHoodleMap pagenum hdl pdim = PageDimension $ view gdimension pg (hadj,vadj) = view adjustments cinfo- (xpos,ypos) <- (,) <$> adjustmentGetValue hadj <*> adjustmentGetValue vadj + (xpos,ypos) <- (,) <$> Gtk.adjustmentGetValue hadj <*> Gtk.adjustmentGetValue vadj let arr = makeSingleArrangement zmode pdim cdim (xpos,ypos) vinfo = view viewInfo cinfo nvinfo = xfrmViewInfo (const arr) vinfo@@ -108,8 +106,8 @@ canvas = view drawArea cinfo zmode = view (viewInfo.zoomMode) cinfo (hadj,vadj) = view adjustments cinfo- (xdesk,ydesk) <- (,) <$> adjustmentGetValue hadj - <*> adjustmentGetValue vadj + (xdesk,ydesk) <- (,) <$> Gtk.adjustmentGetValue hadj + <*> Gtk.adjustmentGetValue vadj geometry <- makeCanvasGeometry (PageNum pagenum) oarr canvas case desktop2Page geometry (DeskCoord (xdesk,ydesk)) of Nothing -> return (CanvasContPage cinfo)@@ -131,19 +129,19 @@ updateCvsInfoFrmHoodle hdl c -- | -setPage :: HoodleState -> PageNum -> CanvasId -> IO CanvasInfoBox-setPage xstate pnum cid = do - let cinfobox = getCanvasInfo cid xstate- unboxBiAct (liftM CanvasSinglePage . setPageSingle xstate pnum) - (liftM CanvasContPage . setPageCont xstate pnum)+setPage :: UnitHoodle -> PageNum -> CanvasId -> IO CanvasInfoBox+setPage uhdl pnum cid = do + let cinfobox = getCanvasInfo cid uhdl+ unboxBiAct (liftM CanvasSinglePage . setPageSingle uhdl pnum) + (liftM CanvasContPage . setPageCont uhdl pnum) cinfobox -- | setPageSingle : in Single Page mode -setPageSingle :: HoodleState -> PageNum +setPageSingle :: UnitHoodle -> PageNum -> CanvasInfo SinglePage -> IO (CanvasInfo SinglePage)-setPageSingle xstate pnum cinfo = do - let hdl = getHoodle xstate+setPageSingle uhdl pnum cinfo = do + let hdl = getHoodle uhdl geometry <- getCvsGeomFrmCvsInfo cinfo let cdim = canvasDim geometry let pg = getPageFromGHoodleMap (unPageNum pnum) hdl@@ -154,20 +152,17 @@ . set (viewInfo.pageArrangement) arr $ cinfo -- | setPageCont : in Continuous Page mode -setPageCont :: HoodleState -> PageNum +setPageCont :: UnitHoodle -> PageNum -> CanvasInfo ContinuousPage -> IO (CanvasInfo ContinuousPage)-setPageCont xstate pnum cinfo = do - let hdl = getHoodle xstate+setPageCont uhdl pnum cinfo = do + let hdl = getHoodle uhdl geometry <- getCvsGeomFrmCvsInfo cinfo let cdim = canvasDim geometry zmode = view (viewInfo.zoomMode) cinfo arr = makeContinuousArrangement zmode cdim hdl (pnum,PageCoord (0,0)) return $ set currentPageNum (unPageNum pnum) . set (viewInfo.pageArrangement) arr $ cinfo -- - -- | need to be refactored into zoomRatioFrmRelToCurr (rename zoomRatioRelPredefined) relZoomRatio :: CanvasGeometry -> ZoomModeRel -> Double
src/Hoodle/ModelAction/Pen.hs view
@@ -3,7 +3,7 @@ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.ModelAction.Pen --- Copyright : (c) 2011-2014 Ian-Woo Kim+-- Copyright : (c) 2011-2015 Ian-Woo Kim -- -- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>@@ -14,26 +14,17 @@ module Hoodle.ModelAction.Pen where -import Control.Lens (view,set,over)+import Control.Lens (view) import Control.Monad (when)-import Control.Monad.Identity (runIdentity) import Data.Foldable-import qualified Data.IntMap as IM import Data.Sequence hiding (take, drop) import Data.Strict.Tuple hiding (uncurry) import qualified Graphics.Rendering.Cairo as Cairo -- from hoodle-platform -import Data.Hoodle.BBox-import Data.Hoodle.Generic import Data.Hoodle.Simple-import Graphics.Hoodle.Render-import Graphics.Hoodle.Render.Type -- from this package -import Hoodle.ModelAction.Layer-import Hoodle.ModelAction.Page import Hoodle.Type.Canvas import Hoodle.Type.Enum-import Hoodle.Type.PageArrangement -- data TempRender a = TempRender { tempSurfaceSrc :: Cairo.Surface @@ -65,7 +56,7 @@ ptool = case ptype of PenWork -> "pen" HighlighterWork -> "highlighter"- _ -> error "error in addPDraw"+ _ -> error "error in createNewStroke" newstroke = case pvwpen of @@ -78,25 +69,4 @@ , stroke_vwdata = map (\(x,y,z)->(x,y,pwidth*z)) . toList $ pdraw } in newstroke ---- | -addPDraw :: RenderCache- -> PenInfo - -> RHoodle- -> PageNum - -> Seq (Double,Double,Double) - -> IO (RHoodle,BBox) -- ^ new hoodle and bbox in page coordinate-addPDraw cache pinfo hdl (PageNum pgnum) pdraw = do - let currpage = getPageFromGHoodleMap pgnum hdl- currlayer = getCurrentLayer currpage- dim = view gdimension currpage- newstroke = createNewStroke pinfo pdraw - newstrokebbox = runIdentity (makeBBoxed newstroke)- bbox = getBBox newstrokebbox- newlayerbbox <- updateLayerBuf cache dim (Just bbox)- . over gitems (++[RItemStroke newstrokebbox]) - $ currlayer- let newpagebbox = adjustCurrentLayer newlayerbbox currpage - newhdlbbox = set gpages (IM.adjust (const newpagebbox) pgnum (view gpages hdl) ) hdl - return (newhdlbbox,bbox)
src/Hoodle/ModelAction/Select.hs view
@@ -27,7 +27,7 @@ import Data.Time.Clock import qualified Graphics.Rendering.Cairo as Cairo import Graphics.Rendering.Cairo.Matrix ( invert, transformPoint )-import Graphics.UI.Gtk hiding (get,set)+import qualified Graphics.UI.Gtk as Gtk -- from hoodle-platform import Data.Hoodle.Generic import Data.Hoodle.BBox@@ -65,10 +65,10 @@ -- | scaleFromToBBox :: BBox -> BBox -> (Double,Double) -> (Double,Double) scaleFromToBBox (BBox (ox1,oy1) (ox2,oy2)) (BBox (nx1,ny1) (nx2,ny2)) (x,y) = - let scalex = (nx2-nx1) / (ox2-ox1)- scaley = (ny2-ny1) / (oy2-oy1) - nx = (x-ox1)*scalex+nx1- ny = (y-oy1)*scaley+ny1+ let sx = (nx2-nx1) / (ox2-ox1)+ sy = (ny2-ny1) / (oy2-oy1) + nx = (x-ox1)*sx+nx1+ ny = (y-oy1)*sy+ny1 in (nx,ny) -- |@@ -86,17 +86,13 @@ where coordtrans (x,y) = unCvsCoord . desktop2Canvas geometry . page2Desktop geometry $ (pnum,PageCoord (x,y)) --- nbbox = bboxFromImage nimg--- in ImageBBox nimg nbbox-- -- | getSelectedItms :: Page SelectMode -> [RItem] getSelectedItms = either (const []) (concatMap unHitted . getB) . rItmsInActiveLyr -- |-getSelectedItmsFromHoodleState :: HoodleState -> Maybe [RItem] -getSelectedItmsFromHoodleState xstate = - case view hoodleModeState xstate of +getSelectedItmsFromUnitHoodle :: UnitHoodle -> Maybe [RItem] +getSelectedItmsFromUnitHoodle uhdl = + case view hoodleModeState uhdl of ViewAppendState _ -> Nothing SelectState thdl -> fmap (getSelectedItms.Prelude.snd) (view gselSelected thdl) @@ -124,30 +120,17 @@ + -- | updateTempHoodleSelect :: Hoodle SelectMode -> Page SelectMode -> Int -> Hoodle SelectMode updateTempHoodleSelect thdl tpage pagenum = let pgs = view gselAll thdl pgs' = M.adjust (const (hPage2RPage tpage)) pagenum pgs- in set gselAll pgs' - . set gselSelected (Just (pagenum,tpage))- $ thdl - --- |-updateTempHoodleSelectIO :: RenderCache - -> Hoodle SelectMode - -> Page SelectMode - -> Int- -> IO (Hoodle SelectMode)-updateTempHoodleSelectIO cache thdl tpage pagenum = do - let pgs = view gselAll thdl - newpage <- (updatePageBuf cache . hPage2RPage) tpage- let pgs' = M.adjust (const newpage) pagenum pgs- return $ set gselAll pgs' - . set gselSelected (Just (pagenum,tpage))- $ thdl + in set gselAll pgs' . set gselSelected (Just (pagenum,tpage)) $ thdl + + -- | calculateWholeBBox :: [BBoxed Stroke] -> Maybe BBox calculateWholeBBox = toMaybe . mconcat . map ( Union . Middle. getBBox ) @@ -181,27 +164,27 @@ -- |-toggleCutCopyDelete :: UIManager -> Bool -> IO ()+toggleCutCopyDelete :: Gtk.UIManager -> Bool -> IO () toggleCutCopyDelete ui b = do - agr <- uiManagerGetActionGroups ui >>= \x -> + agr <- Gtk.uiManagerGetActionGroups ui >>= \x -> case x of [] -> error "No action group?" y:_ -> return y- Just deletea <- actionGroupGetAction agr "DELETEA"- Just copya <- actionGroupGetAction agr "COPYA"- Just cuta <- actionGroupGetAction agr "CUTA"+ Just deletea <- Gtk.actionGroupGetAction agr "DELETEA"+ Just copya <- Gtk.actionGroupGetAction agr "COPYA"+ Just cuta <- Gtk.actionGroupGetAction agr "CUTA" let copycutdeletea = [copya,cuta,deletea] - mapM_ (flip actionSetSensitive b) copycutdeletea+ mapM_ (flip Gtk.actionSetSensitive b) copycutdeletea -- |-togglePaste :: UIManager -> Bool -> IO ()+togglePaste :: Gtk.UIManager -> Bool -> IO () togglePaste ui b = do - agr <- uiManagerGetActionGroups ui >>= \x -> + agr <- Gtk.uiManagerGetActionGroups ui >>= \x -> case x of [] -> error "No action group?" y:_ -> return y- Just pastea <- actionGroupGetAction agr "PASTEA"- actionSetSensitive pastea b+ Just pastea <- Gtk.actionGroupGetAction agr "PASTEA"+ Gtk.actionSetSensitive pastea b -- | changeStrokeColor :: PenColor -> BBoxed Stroke -> BBoxed Stroke@@ -349,10 +332,10 @@ -- | -mkItmsNImg :: RenderCache -> Page SelectMode -> IO ItmsNImg-mkItmsNImg cache tpage = do +mkItmsNImg :: RenderCache -> CanvasId -> Page SelectMode -> IO ItmsNImg+mkItmsNImg cache cid tpage = do let itms = getSelectedItms tpage- drawselection = mapM_ (renderRItem cache) itms + drawselection = mapM_ (renderRItem cache cid) itms Dim cw ch = view gdimension tpage mbbox = case getULBBoxFromSelected tpage of Middle bbox -> Just bbox
src/Hoodle/ModelAction/Text.hs view
@@ -5,7 +5,7 @@ -- Module : Hoodle.ModelAction.File -- Copyright : (c) 2011-2014 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -17,10 +17,8 @@ import Control.Applicative import Data.Attoparsec.Text as A import Data.Char (isAlphaNum)-import qualified Data.Map as M+import qualified Data.HashMap.Strict as M import qualified Data.Text as T-import qualified Data.Text.Encoding as TE-import qualified Data.Text.IO as TIO -- import Debug.Trace @@ -38,7 +36,7 @@ -} -- | -getKeywordMap :: T.Text -> M.Map T.Text T.Text+getKeywordMap :: T.Text -> M.HashMap T.Text T.Text getKeywordMap txt = case parseOnly (many keywordContents) txt of Left err -> trace (show err) $ M.empty Right lst -> M.fromList lst@@ -69,6 +67,11 @@ txt <- T.unlines <$> manyTill oneline keywordEnd return (k,txt) -+-- |+extractKeyword :: T.Text -> Maybe T.Text+extractKeyword txt = + case T.unpack txt of+ 'e':'m':'b':'e':'d':'l':'a':'t':'e':'x':':':'k':'e':'y':'w':'o':'r':'d':':':xs -> Just (T.pack xs)+ _ -> Nothing
src/Hoodle/ModelAction/Window.hs view
@@ -1,12 +1,13 @@-{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-} ----------------------------------------------------------------------------- -- | -- Module : Hoodle.ModelAction.Window --- Copyright : (c) 2011-2014 Ian-Woo Kim+-- Copyright : (c) 2011-2015 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -16,28 +17,35 @@ module Hoodle.ModelAction.Window where -- from other packages-import Control.Concurrent-import Control.Concurrent.STM import Control.Lens (view)-import Control.Monad-import Control.Monad.Trans +import Control.Monad hiding (forM_)+import Control.Monad.Trans+import Data.Foldable (forM_) import qualified Data.IntMap as M+import Data.IORef (newIORef, readIORef)+import Data.Traversable (traverse)+import Data.UUID (UUID)+import Data.UUID.V4+#ifdef HUB+import Control.Concurrent+import Control.Concurrent.STM import Data.Maybe (mapMaybe) import qualified Data.Text as T-import DBus+import DBus hiding (UUID) import DBus.Client-import Graphics.UI.Gtk hiding (get,set)-import qualified Graphics.UI.Gtk as Gtk (set)+#endif+import qualified Graphics.UI.Gtk as Gtk import System.FilePath -- from this package import Hoodle.Device import Hoodle.Type.Canvas import Hoodle.Type.Event-import Hoodle.Type.Window import Hoodle.Type.HoodleState+import Hoodle.Type.Window import Hoodle.Util -- +#ifdef HUB getDBUSEvent :: (AllEvent -> IO ()) -> TVar Bool -> IO () getDBUSEvent callback tvar = do client <- connectSession@@ -56,243 +64,280 @@ let fps = mapMaybe fromVariant (signalBody sig) :: [T.Text] b <- atomically (readTVar tvar) when ((not.null) fps && b) $ do - (postGUISync . callback . UsrEv . DBusEv . ImageFileDropped . T.unpack . head) + (Gtk.postGUISync . callback . UsrEv . DBusEv . ImageFileDropped . T.unpack . head) fps return () getLaTeX sig = do let latex = mapMaybe fromVariant (signalBody sig) :: [T.Text] b <- atomically (readTVar tvar) when ((not.null) latex && b) $ do - (postGUISync . callback . UsrEv . DBusEv . DBusNetworkInput . head) + (Gtk.postGUISync . callback . UsrEv . DBusEv . DBusNetworkInput . head) latex return ()+#endif -- | set frame title according to file name setTitleFromFileName :: HoodleState -> IO () setTitleFromFileName xstate = do - case view (hoodleFileControl.hoodleFileName) xstate of- Nothing -> Gtk.set (view rootOfRootWindow xstate) - [ windowTitle := "untitled" ]- Just filename -> Gtk.set (view rootOfRootWindow xstate) - [ windowTitle := takeFileName filename] + case view (unitHoodles.currentUnit.hoodleFileControl.hoodleFileName) xstate of+ LocalDir Nothing -> Gtk.set (view rootOfRootWindow xstate) + [ Gtk.windowTitle Gtk.:= ("untitled" :: String) ]+ LocalDir (Just filename) -> Gtk.set (view rootOfRootWindow xstate) + [ Gtk.windowTitle Gtk.:= takeFileName filename] + TempDir _filename -> Gtk.set (view rootOfRootWindow xstate) + [ Gtk.windowTitle Gtk.:= ("shared document" :: String)] -- | newCanvasId :: CanvasInfoMap -> CanvasId -newCanvasId cmap = - let cids = M.keys cmap - in (maximum cids) + 1 +newCanvasId cmap = let cids = M.keys cmap in (maximum cids) + 1 -- | initialize CanvasInfo with creating windows and connect events-initCanvasInfo :: HoodleState -> CanvasId -> IO (CanvasInfo a)-initCanvasInfo xstate cid = - minimalCanvasInfo xstate cid >>= connectDefaultEventCanvasInfo xstate+initCanvasInfo :: HoodleState -> UnitHoodle -> CanvasId -> IO (CanvasInfo a)+initCanvasInfo xstate uhdl cid = + minimalCanvasInfo cid >>= connectDefaultEventCanvasInfo xstate uhdl -- | only creating windows -minimalCanvasInfo :: HoodleState -> CanvasId -> IO (CanvasInfo a)-minimalCanvasInfo _xstate cid = do - canvas <- drawingAreaNew- scrwin <- scrolledWindowNew Nothing Nothing - containerAdd scrwin canvas- hadj <- adjustmentNew 0 0 500 100 200 200 - vadj <- adjustmentNew 0 0 500 100 200 200 - scrolledWindowSetHAdjustment scrwin hadj - scrolledWindowSetVAdjustment scrwin vadj +minimalCanvasInfo :: CanvasId -> IO (CanvasInfo a)+minimalCanvasInfo cid = do+ canvas <- Gtk.drawingAreaNew+ scrwin <- Gtk.scrolledWindowNew Nothing Nothing + Gtk.containerAdd scrwin canvas+ hadj <- Gtk.adjustmentNew 0 0 500 100 200 200 + vadj <- Gtk.adjustmentNew 0 0 500 100 200 200 + Gtk.scrolledWindowSetHAdjustment scrwin hadj + Gtk.scrolledWindowSetVAdjustment scrwin vadj return $ CanvasInfo cid canvas Nothing scrwin (error "no viewInfo" :: ViewInfo a) 0 hadj vadj Nothing Nothing defaultCanvasWidgets Nothing -- | only connect events - connectDefaultEventCanvasInfo - :: HoodleState -> CanvasInfo a -> IO (CanvasInfo a )-connectDefaultEventCanvasInfo xstate cinfo = do + :: HoodleState -> UnitHoodle -> CanvasInfo a -> IO (CanvasInfo a )+connectDefaultEventCanvasInfo xstate _uhdl cinfo = do let callback = view callBack xstate+ ui = view gtkUIManager xstate dev = view deviceList xstate canvas = _drawArea cinfo cid = _canvasId cinfo scrwin = _scrolledWindow cinfo hadj = _horizAdjustment cinfo - vadj = _vertAdjustment cinfo -- widgetSetCanFocus canvas True - widgetGrabFocus canvas - - _sizereq <- canvas `on` sizeRequest $ return (Requisition 800 400) - - _keyevent <- canvas `on` keyPressEvent $ tryEvent $ do - m <- eventModifier- n <- eventKeyName + vadj = _vertAdjustment cinfo+ Gtk.widgetSetCanFocus canvas True + Gtk.widgetGrabFocus canvas +#ifdef GTK3+ {- +#endif+ _sizereq <- canvas `Gtk.on` Gtk.sizeRequest $ return (Gtk.Requisition 800 400)+ _keyevent <- canvas `Gtk.on` Gtk.keyPressEvent $ Gtk.tryEvent $ do + m <- Gtk.eventModifier+ n <- Gtk.eventKeyName let keystr = show m ++ ":" ++ show n liftIO $ (callback (UsrEv (CustomKeyEvent keystr)))- _bpevent <- canvas `on` buttonPressEvent $ tryEvent $ do - liftIO $ widgetGrabFocus canvas - (mbtn,mp) <- getPointer dev- case mp of - Nothing -> return ()- Just p -> do - let pbtn = maybe PenButton1 id mbtn- case pbtn of - TouchButton -> liftIO (callback (UsrEv (TouchDown cid p)))- _ -> liftIO (callback (UsrEv (PenDown cid pbtn p)))- _confevent <- canvas `on` configureEvent $ tryEvent $ do - (w,h) <- eventSize - liftIO $ callback (UsrEv (CanvasConfigure cid (fromIntegral w) (fromIntegral h)))- _brevent <- canvas `on` buttonReleaseEvent $ tryEvent $ do + _bpevent <- canvas `Gtk.on` Gtk.buttonPressEvent $ Gtk.tryEvent $ do + liftIO $ Gtk.widgetGrabFocus canvas (mbtn,mp) <- getPointer dev- case mp of - Nothing -> return () - Just p -> do- let pbtn = maybe PenButton1 id mbtn- case pbtn of - TouchButton -> (liftIO . callback . UsrEv) (TouchUp cid p)- _ -> (liftIO . callback . UsrEv) (PenUp cid p)- + forM_ mp $ \p -> do + let pbtn = maybe PenButton1 id mbtn+ case pbtn of + TouchButton -> liftIO (callback (UsrEv (TouchDown cid p)))+ _ -> liftIO (callback (UsrEv (PenDown cid pbtn p)))+ _confevent <- canvas `Gtk.on` Gtk.configureEvent $ Gtk.tryEvent $ do + (w,h) <- Gtk.eventSize + liftIO $ callback (UsrEv (CanvasConfigure cid (fromIntegral w) (fromIntegral h)))+ _brevent <- canvas `Gtk.on` Gtk.buttonReleaseEvent $ Gtk.tryEvent $ do + (mbtn,mp) <- getPointer dev+ forM_ mp $ \p -> do + let pbtn = maybe PenButton1 id mbtn+ case pbtn of + TouchButton -> (liftIO . callback . UsrEv) (TouchUp cid p)+ _ -> (liftIO . callback . UsrEv) (PenUp cid p)+#ifdef HUB tvar <- newTVarIO False forkIO $ getDBUSEvent callback tvar- _focus <- canvas `on` focusInEvent $ tryEvent $ liftIO $ do+ _focus <- canvas `Gtk.on` Gtk.focusInEvent $ Gtk.tryEvent $ liftIO $ do atomically (writeTVar tvar True)- widgetGrabFocus canvas - _focusout <- canvas `on` focusOutEvent $ tryEvent $ liftIO $ atomically (writeTVar tvar False)- _exposeev <- canvas `on` exposeEvent $ tryEvent $ do - liftIO $ widgetGrabFocus canvas + Gtk.widgetGrabFocus canvas + _focusout <- canvas `Gtk.on` Gtk.focusOutEvent $ Gtk.tryEvent $ liftIO $ atomically (writeTVar tvar False)+#endif+++#ifdef GTK3+ _exposeev <- canvas `Gtk.on` Gtk.draw $ do +#else+ _exposeev <- canvas `Gtk.on` Gtk.exposeEvent $ Gtk.tryEvent $ do +#endif+ liftIO $ Gtk.widgetGrabFocus canvas (liftIO . callback . UsrEv) (UpdateCanvas cid) - canvas `on` motionNotifyEvent $ tryEvent $ do + canvas `Gtk.on` Gtk.motionNotifyEvent $ Gtk.tryEvent $ do (mbtn,mp) <- getPointer dev- case mp of - Nothing -> return ()- Just p -> do - let pbtn = maybe PenButton1 id mbtn - case pbtn of - TouchButton -> (liftIO . callback . UsrEv) (TouchMove cid p) - _ -> (liftIO . callback . UsrEv) (PenMove cid p)-+ forM_ mp $ \p -> do+ let pbtn = maybe PenButton1 id mbtn + case pbtn of + TouchButton -> (liftIO . callback . UsrEv) (TouchMove cid p) + _ -> (liftIO . callback . UsrEv) (PenMove cid p) -- drag and drop setting- dragDestSet canvas [DestDefaultMotion, DestDefaultDrop] [ActionCopy]- dragDestAddTextTargets canvas- canvas `on` dragDataReceived $ \_dc pos _i _ts -> do - s <- selectionDataGetText + Gtk.dragDestSet canvas [Gtk.DestDefaultMotion, Gtk.DestDefaultDrop] [Gtk.ActionCopy]+ Gtk.dragDestAddTextTargets canvas+ canvas `Gtk.on` Gtk.dragDataReceived $ \_dc pos _i _ts -> do + s <- Gtk.selectionDataGetText (liftIO . callback . UsrEv) (GotLink s pos) - widgetAddEvents canvas [PointerMotionMask,Button1MotionMask,KeyPressMask] - let ui = view gtkUIManager xstate - agr <- liftIO ( uiManagerGetActionGroups ui >>= \x ->+ Gtk.widgetAddEvents canvas [Gtk.PointerMotionMask,Gtk.Button1MotionMask,Gtk.KeyPressMask]+ agr <- liftIO ( Gtk.uiManagerGetActionGroups ui >>= \x -> case x of [] -> error "No action group? " y:_ -> return y )- uxinputa <- liftIO (actionGroupGetAction agr "UXINPUTA" >>= \(Just x) -> - return (castToToggleAction x) )- b <- liftIO $ toggleActionGetActive uxinputa- if b then widgetSetExtensionEvents canvas [ExtensionEventsAll]- else widgetSetExtensionEvents canvas [ExtensionEventsNone]- hadjconnid <- afterValueChanged hadj $ do - v <- adjustmentGetValue hadj + uxinputa <- liftIO (Gtk.actionGroupGetAction agr ("UXINPUTA" :: String) >>= \(Just x) -> + return (Gtk.castToToggleAction x) )+ b <- liftIO $ Gtk.toggleActionGetActive uxinputa+#ifdef GTK3 +#else+ if b then Gtk.widgetSetExtensionEvents canvas [Gtk.ExtensionEventsAll]+ else Gtk.widgetSetExtensionEvents canvas [Gtk.ExtensionEventsNone]+#endif+ hadjconnid <- Gtk.afterValueChanged hadj $ do + v <- Gtk.adjustmentGetValue hadj (callback . UsrEv) (HScrollBarMoved cid v)- vadjconnid <- afterValueChanged vadj $ do - v <- adjustmentGetValue vadj + vadjconnid <- Gtk.afterValueChanged vadj $ do + v <- Gtk.adjustmentGetValue vadj (callback . UsrEv) (VScrollBarMoved cid v)- Just vscrbar <- scrolledWindowGetVScrollbar scrwin- _bpevtvscrbar <- vscrbar `on` buttonPressEvent $ do - v <- liftIO $ adjustmentGetValue vadj + Just vscrbar <- Gtk.scrolledWindowGetVScrollbar scrwin+ _bpevtvscrbar <- vscrbar `Gtk.on` Gtk.buttonPressEvent $ do + v <- liftIO $ Gtk.adjustmentGetValue vadj liftIO ((callback . UsrEv) (VScrollBarStart cid v)) return False- _brevtvscrbar <- vscrbar `on` buttonReleaseEvent $ do - v <- liftIO $ adjustmentGetValue vadj + _brevtvscrbar <- vscrbar `Gtk.on` Gtk.buttonReleaseEvent $ do + v <- liftIO $ Gtk.adjustmentGetValue vadj liftIO ((callback . UsrEv) (VScrollBarEnd cid v)) return False return $ cinfo { _horizAdjConnId = Just hadjconnid , _vertAdjConnId = Just vadjconnid }- --- | recreate windows from old canvas info but no event connect+#ifdef GTK3+ -}+#endif+ -- temp+ return $ cinfo +-- | recreate windows from old canvas info but no event connect reinitCanvasInfoStage1 - :: HoodleState -> CanvasInfo a -> IO (CanvasInfo a)-reinitCanvasInfoStage1 xstate oldcinfo = do + :: UnitHoodle -> CanvasInfo a -> IO (CanvasInfo a)+reinitCanvasInfoStage1 _uhdl oldcinfo = do let cid = view canvasId oldcinfo - newcinfo <- minimalCanvasInfo xstate cid + newcinfo <- minimalCanvasInfo cid return $ newcinfo { _viewInfo = _viewInfo oldcinfo , _currentPageNum = _currentPageNum oldcinfo } -- | event connect- reinitCanvasInfoStage2 - :: HoodleState -> CanvasInfo a -> IO (CanvasInfo a)-reinitCanvasInfoStage2 = connectDefaultEventCanvasInfo+ :: HoodleState -> UnitHoodle -> CanvasInfo a -> IO (CanvasInfo a)+reinitCanvasInfoStage2 = connectDefaultEventCanvasInfo -- | event connecting for all windows - -eventConnect :: HoodleState -> WindowConfig - -> IO (HoodleState,WindowConfig)-eventConnect xstate (Node cid) = do - let cmap = getCanvasInfoMap xstate +eventConnect :: HoodleState -> UnitHoodle -> WindowConfig -> IO (UnitHoodle,WindowConfig)+eventConnect xst uhdl (Node cid) = do + let cmap = view cvsInfoMap uhdl cinfobox = maybeError' "eventConnect" $ M.lookup cid cmap- ncinfobox <- forBoth unboxBiXform (reinitCanvasInfoStage2 xstate) cinfobox- let xstate' = updateFromCanvasInfoAsCurrentCanvas ncinfobox xstate- return (xstate', Node cid) -eventConnect xstate (HSplit wconf1 wconf2) = do - (xstate',wconf1') <- eventConnect xstate wconf1 - (xstate'',wconf2') <- eventConnect xstate' wconf2 - return (xstate'',HSplit wconf1' wconf2')-eventConnect xstate (VSplit wconf1 wconf2) = do - (xstate',wconf1') <- eventConnect xstate wconf1 - (xstate'',wconf2') <- eventConnect xstate' wconf2 - return (xstate'',VSplit wconf1' wconf2')+ ncinfobox <- forBoth unboxBiXform (reinitCanvasInfoStage2 xst uhdl) cinfobox+ let uhdl' = updateFromCanvasInfoAsCurrentCanvas ncinfobox uhdl+ return (uhdl', Node cid) +eventConnect xst uhdl (HSplit wconf1 wconf2) = do + (uhdl',wconf1') <- eventConnect xst uhdl wconf1 + (uhdl'',wconf2') <- eventConnect xst uhdl' wconf2 + return (uhdl'',HSplit wconf1' wconf2')+eventConnect xst uhdl (VSplit wconf1 wconf2) = do + (uhdl',wconf1') <- eventConnect xst uhdl wconf1 + (uhdl'',wconf2') <- eventConnect xst uhdl' wconf2 + return (uhdl'',VSplit wconf1' wconf2') -- | default construct frame --constructFrame :: HoodleState -> WindowConfig - -> IO (HoodleState,Widget,WindowConfig)-constructFrame hst wcfg = constructFrame' (CanvasSinglePage defaultCvsInfoSinglePage) hst wcfg --+constructFrame :: HoodleState + -> UnitHoodle -> WindowConfig + -> IO (UnitHoodle,Gtk.Widget,WindowConfig)+constructFrame xst uhdl wcfg = + let callback = view callBack xst+ in constructFrame' callback (CanvasSinglePage defaultCvsInfoSinglePage) uhdl wcfg -- | construct frames with template--constructFrame' :: CanvasInfoBox -> - HoodleState -> WindowConfig - -> IO (HoodleState,Widget,WindowConfig)-constructFrame' template oxstate (Node cid) = do - let ocmap = getCanvasInfoMap oxstate - (cinfobox,_cmap,xstate) <- case M.lookup cid ocmap of - Just cinfobox' -> return (cinfobox',ocmap,oxstate)+constructFrame' :: (AllEvent -> IO ()) -> CanvasInfoBox -> UnitHoodle -> WindowConfig + -> IO (UnitHoodle,Gtk.Widget,WindowConfig)+constructFrame' _callback template ouhdl (Node cid) = do + let ocmap = view cvsInfoMap ouhdl+ (cinfobox,_cmap,uhdl) <- case M.lookup cid ocmap of + Just cinfobox' -> return (cinfobox',ocmap,ouhdl) Nothing -> do let cinfobox' = setCanvasId cid template cmap' = M.insert cid cinfobox' ocmap- xstate' = maybe oxstate id (setCanvasInfoMap cmap' oxstate)- return (cinfobox',cmap',xstate')- ncinfobox <- forBoth unboxBiXform (reinitCanvasInfoStage1 xstate) cinfobox- let xstate' = updateFromCanvasInfoAsCurrentCanvas ncinfobox xstate- let scrwin = forBoth' unboxBiAct (castToWidget.view scrolledWindow) ncinfobox- return (xstate', scrwin, Node cid)-constructFrame' template xstate (HSplit wconf1 wconf2) = do - (xstate',win1,wconf1') <- constructFrame' template xstate wconf1 - (xstate'',win2,wconf2') <- constructFrame' template xstate' wconf2 - let callback = view callBack xstate'' - hpane' <- hPanedNew- hpane' `on` buttonPressEvent $ do + uhdl' = maybe ouhdl id (setCanvasInfoMap cmap' ouhdl)+ return (cinfobox',cmap',uhdl')+ ncinfobox <- forBoth unboxBiXform (reinitCanvasInfoStage1 uhdl) cinfobox+ let uhdl' = updateFromCanvasInfoAsCurrentCanvas ncinfobox uhdl+ forBoth' unboxBiAct (putStrLn <=< Gtk.widgetGetName . view drawArea) ncinfobox+ let scrwin = forBoth' unboxBiAct (Gtk.castToWidget.view scrolledWindow) ncinfobox+ return (uhdl', scrwin, Node cid)+constructFrame' callback template uhdl (HSplit wconf1 wconf2) = do + (uhdl',win1,wconf1') <- constructFrame' callback template uhdl wconf1+ (uhdl'',win2,wconf2') <- constructFrame' callback template uhdl' wconf2 + hpane' <- Gtk.hPanedNew+ hpane' `Gtk.on` Gtk.buttonPressEvent $ do liftIO ((callback . UsrEv) PaneMoveStart) return False - hpane' `on` buttonReleaseEvent $ do + hpane' `Gtk.on` Gtk.buttonReleaseEvent $ do liftIO ((callback . UsrEv) PaneMoveEnd) return False - panedPack1 hpane' win1 True False- panedPack2 hpane' win2 True False- widgetShowAll hpane' - return (xstate'',castToWidget hpane', HSplit wconf1' wconf2')-constructFrame' template xstate (VSplit wconf1 wconf2) = do - (xstate',win1,wconf1') <- constructFrame' template xstate wconf1 - (xstate'',win2,wconf2') <- constructFrame' template xstate' wconf2 - let callback = view callBack xstate'' - vpane' <- vPanedNew - vpane' `on` buttonPressEvent $ do + Gtk.panedPack1 hpane' win1 True False+ Gtk.panedPack2 hpane' win2 True False+ Gtk.widgetShowAll hpane' + return (uhdl'',Gtk.castToWidget hpane', HSplit wconf1' wconf2')+constructFrame' callback template uhdl (VSplit wconf1 wconf2) = do + (uhdl',win1,wconf1') <- constructFrame' callback template uhdl wconf1 + (uhdl'',win2,wconf2') <- constructFrame' callback template uhdl' wconf2 + vpane' <- Gtk.vPanedNew + vpane' `Gtk.on` Gtk.buttonPressEvent $ do liftIO ((callback . UsrEv) PaneMoveStart) return False - vpane' `on` buttonReleaseEvent $ do + vpane' `Gtk.on` Gtk.buttonReleaseEvent $ do liftIO ((callback . UsrEv) PaneMoveEnd) return False - panedPack1 vpane' win1 True False- panedPack2 vpane' win2 True False- widgetShowAll vpane' - return (xstate'',castToWidget vpane', VSplit wconf1' wconf2')+ Gtk.panedPack1 vpane' win1 True False+ Gtk.panedPack2 vpane' win2 True False+ Gtk.widgetShowAll vpane' + return (uhdl'',Gtk.castToWidget vpane', VSplit wconf1' wconf2') +registerFrameToContainer :: Gtk.Window -> Gtk.Box -> Gtk.Widget -> IO ()+registerFrameToContainer rtrwin rtcntr win = do+ Gtk.boxPackEnd rtcntr win Gtk.PackGrow 0 + -- Gtk.widgetShowAll rtcntr + Gtk.widgetShowAll rtrwin+ Gtk.widgetQueueDraw rtrwin+++createTab :: (AllEvent -> IO ()) -> Gtk.Notebook -> Gtk.VBox -> IO (Int,UUID,Gtk.Button)+createTab callback notebook vboxcvs = do+ hbox <- Gtk.hBoxNew False 0 + ebox <- Gtk.eventBoxNew+ label <- Gtk.labelNew (Just " " :: Maybe String)+ Gtk.containerAdd ebox label+ Gtk.dragSourceSet ebox [Gtk.Button1] [Gtk.ActionCopy]+ Gtk.dragSourceSetIconStock ebox Gtk.stockIndex+ Gtk.dragSourceAddTextTargets ebox+ button <- Gtk.buttonNewWithLabel ("X" :: String)+ -- Gtk.Gtk.widgetSetSensitive button False+ Gtk.boxPackStart hbox {- label -} ebox Gtk.PackNatural 0+ Gtk.boxPackStart hbox button Gtk.PackNatural 0 + Gtk.widgetShowAll hbox+ mlabel <- Gtk.labelNew (Nothing :: Maybe String)+ n <- Gtk.notebookAppendPageMenu notebook vboxcvs hbox mlabel+ uuid <- nextRandom+ button `Gtk.on` Gtk.buttonActivated $ callback (UsrEv (CloseTab uuid))++ -- ebox `Gtk.on` Gtk.dragBegin $ \_dc -> do + -- liftIO $ putStrLn "dragging"+ ebox `Gtk.on` Gtk.dragDataGet $ \_dc _iid _ts -> do+ minfo <- liftIO $ do + ref <- newIORef (Nothing :: Maybe String)+ callback (UsrEv (GetHoodleFileInfoFromTab uuid ref))+ readIORef ref+ traverse Gtk.selectionDataSetText minfo >> return ()+ return (n,uuid,button)
src/Hoodle/Script.hs view
@@ -1,7 +1,9 @@+{-# LANGUAGE CPP #-}+ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Script--- Copyright : (c) 2012, 2013 Ian-Woo Kim+-- Copyright : (c) 2012-2014 Ian-Woo Kim -- -- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>@@ -13,7 +15,9 @@ module Hoodle.Script where import Hoodle.Script.Hook+#ifdef DYRE import Config.Dyre.Relaunch+#endif -- | @@ -34,10 +38,10 @@ -- | -+#ifdef DYRE relaunchApplication :: IO () relaunchApplication = do putStrLn "relaunching hoodle!" relaunchMaster Nothing - +#endif
src/Hoodle/Script/Coroutine.hs view
@@ -3,7 +3,7 @@ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Script.Coroutine--- Copyright : (c) 2012, 2013 Ian-Woo Kim+-- Copyright : (c) 2012-2015 Ian-Woo Kim -- -- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>@@ -85,3 +85,4 @@ rfilename <- hoist (H.embedPredefinedImage3Hook hset) liftIO rfilename return r +
src/Hoodle/Script/Hook.hs view
@@ -1,7 +1,9 @@+{-# LANGUAGE CPP #-}+ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Script.Hook--- Copyright : (c) 2012, 2013 Ian-Woo Kim+-- Copyright : (c) 2012-2015 Ian-Woo Kim -- -- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>@@ -15,6 +17,9 @@ import Data.Hoodle.Simple import Graphics.Hoodle.Render.Type.Hoodle -- +#ifdef HUB+import Hoodle.Type.Hub+#endif -- | data Hook = Hook { saveAsHook :: Maybe (Hoodle -> IO ())@@ -33,6 +38,10 @@ , warningEmbedImageSize :: Maybe Integer , shrinkCmd4EmbedImage :: Maybe (Double -> FilePath -> FilePath -> IO ()) , getIPaddress :: Maybe (IO String)+#ifdef HUB+ , hubInfo :: Maybe HubInfo+ , sqliteInfo :: Maybe FilePath+#endif } @@ -53,4 +62,8 @@ , warningEmbedImageSize = Nothing , shrinkCmd4EmbedImage = Nothing , getIPaddress = Nothing+#ifdef HUB+ , hubInfo = Nothing+ , sqliteInfo = Nothing+#endif }
src/Hoodle/Type/Alias.hs view
@@ -3,7 +3,7 @@ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Type.Alias--- Copyright : (c) 2012, 2013 Ian-Woo Kim+-- Copyright : (c) 2012-2014 Ian-Woo Kim -- -- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>
src/Hoodle/Type/Canvas.hs view
@@ -75,19 +75,11 @@ , xfrmCvsInfo , xfrmViewInfo , getDrawAreaFromBox--- , unboxGet--- , unboxSet , unboxLens , unboxBiAct , unboxBiXform , forBoth , forBoth'--- , unboxSelect--- , fmap4CvsInfoBox--- , insideAction4CvsInfoBox--- , insideAction4CvsInfoBoxF--- , boxAction--- , selectBox -- * others , updateCanvasDimForSingle , updateCanvasDimForContSingle@@ -98,12 +90,13 @@ import qualified Data.IntMap as M import Data.Sequence import qualified Graphics.Rendering.Cairo as Cairo-import Graphics.UI.Gtk hiding (get,set)+import qualified Graphics.UI.Gtk as Gtk -- import Data.Hoodle.Simple (Dimension(..)) import Data.Hoodle.BBox import Data.Hoodle.Predefined import Graphics.Hoodle.Render.Type.Item+import Graphics.Hoodle.Render.Type.Renderer -- import Hoodle.Type.Enum import Hoodle.Type.PageArrangement@@ -112,9 +105,6 @@ -- |-type CanvasId = Int ---- | data PenDraw = PenDraw { _points :: Seq (Double,Double) } deriving (Show) @@ -138,9 +128,7 @@ emptyPenDraw :: PenDraw emptyPenDraw = PenDraw empty - -- | default view info with single page mode- defaultViewInfoSinglePage :: ViewInfo SinglePage defaultViewInfoSinglePage = ViewInfo { _zoomMode = Original @@ -157,20 +145,18 @@ pageArrangement :: Simple Lens (ViewInfo a) (PageArrangement a) pageArrangement = lens _pageArrangement (\f a -> f { _pageArrangement = a }) -- -- | data CanvasInfo (a :: ViewMode) = CanvasInfo { _canvasId :: CanvasId- , _drawArea :: DrawingArea+ , _drawArea :: Gtk.DrawingArea , _mDrawSurface :: Maybe Cairo.Surface - , _scrolledWindow :: ScrolledWindow+ , _scrolledWindow :: Gtk.ScrolledWindow , _viewInfo :: ViewInfo a , _currentPageNum :: Int- , _horizAdjustment :: Adjustment- , _vertAdjustment :: Adjustment - , _horizAdjConnId :: Maybe (ConnectId Adjustment)- , _vertAdjConnId :: Maybe (ConnectId Adjustment)+ , _horizAdjustment :: Gtk.Adjustment+ , _vertAdjustment :: Gtk.Adjustment + , _horizAdjConnId :: Maybe (Gtk.ConnectId Gtk.Adjustment)+ , _vertAdjConnId :: Maybe (Gtk.ConnectId Gtk.Adjustment) , _canvasWidgets :: CanvasWidgets , _notifiedItem :: Maybe (PageNum,BBox,RItem) }@@ -196,8 +182,8 @@ -- | defaultCvsInfoSinglePage :: CanvasInfo SinglePage defaultCvsInfoSinglePage = - CanvasInfo { _canvasId = error "cvsid"- , _drawArea = error "DrawingArea"+ CanvasInfo { _canvasId = error "defaultCvsInfoSinglePage cvsid"+ , _drawArea = error "defaultCvsInfoSinglePage DrawingArea" , _mDrawSurface = Nothing , _scrolledWindow = error "ScrolledWindow" , _viewInfo = defaultViewInfoSinglePage@@ -215,7 +201,7 @@ canvasId = lens _canvasId (\f a -> f { _canvasId = a }) -- | -drawArea :: Simple Lens (CanvasInfo a) DrawingArea+drawArea :: Simple Lens (CanvasInfo a) Gtk.DrawingArea drawArea = lens _drawArea (\f a -> f { _drawArea = a }) -- | @@ -224,7 +210,7 @@ -- | -scrolledWindow :: Simple Lens (CanvasInfo a) ScrolledWindow+scrolledWindow :: Simple Lens (CanvasInfo a) Gtk.ScrolledWindow scrolledWindow = lens _scrolledWindow (\f a -> f { _scrolledWindow = a }) -- |@@ -236,23 +222,23 @@ currentPageNum = lens _currentPageNum (\f a -> f { _currentPageNum = a }) -- | -horizAdjustment :: Simple Lens (CanvasInfo a) Adjustment +horizAdjustment :: Simple Lens (CanvasInfo a) Gtk.Adjustment horizAdjustment = lens _horizAdjustment (\f a -> f { _horizAdjustment = a }) -- | -vertAdjustment :: Simple Lens (CanvasInfo a) Adjustment +vertAdjustment :: Simple Lens (CanvasInfo a) Gtk.Adjustment vertAdjustment = lens _vertAdjustment (\f a -> f { _vertAdjustment = a }) -- | ConnectId for horizontal scrollbar value change event -horizAdjConnId :: Simple Lens (CanvasInfo a) (Maybe (ConnectId Adjustment))+horizAdjConnId :: Simple Lens (CanvasInfo a) (Maybe (Gtk.ConnectId Gtk.Adjustment)) horizAdjConnId = lens _horizAdjConnId (\f a -> f { _horizAdjConnId = a }) -- | ConnectId for vertical scrollbar value change event -vertAdjConnId :: Simple Lens (CanvasInfo a) (Maybe (ConnectId Adjustment))+vertAdjConnId :: Simple Lens (CanvasInfo a) (Maybe (Gtk.ConnectId Gtk.Adjustment)) vertAdjConnId = lens _vertAdjConnId (\f a -> f { _vertAdjConnId = a }) -- | composition lens-adjustments :: Simple Lens (CanvasInfo a) (Adjustment,Adjustment) +adjustments :: Simple Lens (CanvasInfo a) (Gtk.Adjustment,Gtk.Adjustment) adjustments = lens getter setter where getter = (,) <$> view horizAdjustment <*> view vertAdjustment setter f (h,v) = set horizAdjustment h . set vertAdjustment v $ f@@ -270,25 +256,21 @@ CanvasSinglePage :: CanvasInfo SinglePage -> CanvasInfoBox CanvasContPage :: CanvasInfo ContinuousPage -> CanvasInfoBox ---forBoth :: - ((CanvasInfo SinglePage -> f (CanvasInfo SinglePage))- -> (CanvasInfo ContinuousPage -> f (CanvasInfo ContinuousPage)) - -> (CanvasInfoBox -> f CanvasInfoBox)) - -> (forall a. CanvasInfo a -> f (CanvasInfo a))- -> CanvasInfoBox -> f CanvasInfoBox+forBoth :: ((CanvasInfo SinglePage -> f (CanvasInfo SinglePage))+ -> (CanvasInfo ContinuousPage -> f (CanvasInfo ContinuousPage)) + -> (CanvasInfoBox -> f CanvasInfoBox)) + -> (forall a. CanvasInfo a -> f (CanvasInfo a))+ -> CanvasInfoBox -> f CanvasInfoBox forBoth m f = m f f -forBoth' :: ((CanvasInfo SinglePage -> r)+forBoth' :: ((CanvasInfo SinglePage -> r) -> (CanvasInfo ContinuousPage -> r) -> (CanvasInfoBox -> r) )- -> (forall a. CanvasInfo a -> r)- -> CanvasInfoBox -> r+ -> (forall a. CanvasInfo a -> r)+ -> CanvasInfoBox -> r forBoth' m f = m f f - -- | single page action and continuous page act unboxBiXform :: (Functor f) => (CanvasInfo SinglePage -> f (CanvasInfo SinglePage)) @@ -318,7 +300,7 @@ unboxLens l = lens (unboxGet l) (flip (unboxSet l)) -- |-getDrawAreaFromBox :: CanvasInfoBox -> DrawingArea +getDrawAreaFromBox :: CanvasInfoBox -> Gtk.DrawingArea getDrawAreaFromBox = view (unboxLens drawArea) -- |@@ -338,7 +320,6 @@ penColor :: Simple Lens WidthColorStyle PenColor penColor = lens _penColor (\f a -> f { _penColor = a } ) - -- | data PenHighlighterEraserSet = PenHighlighterEraserSet { _currPen :: WidthColorStyle @@ -369,7 +350,6 @@ currVerticalSpace :: Simple Lens PenHighlighterEraserSet WidthColorStyle currVerticalSpace = lens _currVerticalSpace (\f a -> f { _currVerticalSpace = a } )- -- | data PenInfo = PenInfo { _penType :: PenType@@ -482,5 +462,7 @@ Cairo.rectangle 0 0 w' h' Cairo.fill return sfc ++ return $ (set (viewInfo.pageArrangement) arr'.set mDrawSurface msfc) cinfo
src/Hoodle/Type/Coroutine.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE GADTs #-}+{-# LANGUAGE LambdaCase #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeSynonymInstances #-} {-# LANGUAGE FlexibleInstances #-}@@ -9,7 +10,7 @@ -- Module : Hoodle.Type.Coroutine -- Copyright : (c) 2011-2014 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -115,7 +116,6 @@ -- | doIOaction :: ((AllEvent -> IO ()) -> IO AllEvent) -> MainCoroutine () doIOaction action = modify (tempQueue %~ enqueue (mkIOaction action))-
src/Hoodle/Type/Enum.hs view
@@ -3,7 +3,7 @@ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Type.Enum --- Copyright : (c) 2011-2013 Ian-Woo Kim+-- Copyright : (c) 2011-2014 Ian-Woo Kim -- -- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>@@ -17,9 +17,10 @@ import Control.Lens (Simple,Lens,lens) import qualified Data.ByteString.Char8 as B import qualified Data.Map as M-import Data.Maybe -- import Data.Hoodle.Predefined+--+import Hoodle.Util -- | drawing efficiency data DrawFlag = Clear | BkgEfficient | Efficient@@ -81,6 +82,8 @@ data RotateDir = CW | CCW deriving (Show, Ord, Eq) +-- | +data NewPageModeType = NPPlain | NPLast | NPCycle deriving (Show, Ord, Eq) -- -- lenses@@ -105,12 +108,12 @@ , (ColorWhite, "white") ] penColorRGBAmap :: M.Map PenColor (Double,Double,Double,Double)-penColorRGBAmap = M.fromList $ map (\x->(fst x,fromJust (M.lookup (snd x) predefined_pencolor))) +penColorRGBAmap = M.fromList $ map (\x->(fst x,fromJustError "penColorRGBAmap" (M.lookup (snd x) predefined_pencolor))) $ M.toList penColorNameMap convertPenColorToRGBA :: PenColor -> (Double,Double,Double,Double) convertPenColorToRGBA (ColorRGBA r g b a) = (r,g,b,a)-convertPenColorToRGBA c = fromJust (M.lookup c penColorRGBAmap)+convertPenColorToRGBA c = fromJustError "convertPenColorToRGBA" (M.lookup c penColorRGBAmap) convertRGBAToHex :: (Double,Double,Double,Double) -> B.ByteString convertRGBAToHex = B.pack . rgbaToHEX
src/Hoodle/Type/Event.hs view
@@ -1,11 +1,12 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleInstances #-} ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Type.Event --- Copyright : (c) 2011-2014 Ian-Woo Kim+-- Copyright : (c) 2011-2015 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -21,10 +22,12 @@ import Data.ByteString import Data.IORef import qualified Data.Text as T-import Data.Time.Clock import Data.UUID (UUID) import qualified Graphics.Rendering.Cairo as Cairo-import Graphics.UI.Gtk hiding (Image)+import qualified Graphics.UI.Gtk as Gtk+#ifdef HUB+import Data.Time.Clock+#endif -- from hoodle-platform import Control.Monad.Trans.Crtn.Event import Data.Hoodle.BBox@@ -33,18 +36,24 @@ -- from this package import Hoodle.Device import Hoodle.Type.Enum-import Hoodle.Type.Canvas import Hoodle.Type.PageArrangement+import Hoodle.Util+#ifdef HUB+import Hoodle.Type.Hub+import Hoodle.Type.Synchronization+#endif -- | data AllEvent = UsrEv UserEvent | SysEv SystemEvent deriving Show instance Show (Cairo.Surface) where- show _ = "surface"+ show _ = "cairo surface" -- | -data SystemEvent = TestSystemEvent | ClockUpdateEvent | RenderCacheUpdate (UUID, (Double,Cairo.Surface))+data SystemEvent = TestSystemEvent + | ClockUpdateEvent + | RenderCacheUpdate (SurfaceID, (Double,Cairo.Surface)) deriving Show -- | @@ -62,6 +71,7 @@ | PenWidthChanged Int | AssignPenMode (Either PenType SelectType) | BackgroundStyleChanged BackgroundStyle + | AssignNewPageMode NewPageModeType | HScrollBarMoved Int Double | VScrollBarMoved Int Double | VScrollBarStart Int Double@@ -83,10 +93,13 @@ | LaTeXInput (Maybe (ByteString,ByteString)) | TextInput (Maybe String) | AddLink (Maybe (String,FilePath))+ | OpenLink UrlPath (Maybe (T.Text,T.Text))+ | OpenShared UUID+ | OpenTemp UUID FilePath | EventDisconnected | GetHoodleFileInfo (IORef (Maybe String))+ | GetHoodleFileInfoFromTab UUID (IORef (Maybe String)) | GotLink (Maybe String) (Int,Int)- | Sync UTCTime | FileReloadOrdered | CustomKeyEvent String | GotRevision String String@@ -96,21 +109,37 @@ | GotRecogResult Bool T.Text | MiniBuffer MiniBufferEvent | MultiLine MultiLineEvent- | NetworkProcess NetworkEvent- | DBusEv DBusEvent | RenderEv RenderEvent | LinePosition (Maybe (Int,Int)) | Keyword (Maybe T.Text)+ | SwitchTab Int+ | CloseTab UUID+ | UIEv UIEvent +#ifdef HUB+ | DBusEv DBusEvent+ | NetworkProcess NetworkEvent+ | DisconnectedHub FilePath (FilePath,Maybe FilePath) HubInfo+ | SyncInfoUpdated UUID FileSyncStatus+ | FileSyncFromHub UUID FileSyncStatus+ | GotSyncEvent Bool UUID FileSyncStatus+ | Sync UTCTime + | SyncFileFinished FileSyncStatus+#endif deriving Show instance Show (IORef a) where show _ = "IORef" +data UIEvent = UIGetFlag Bool+ deriving Show++ data RenderEvent = GotRItem RItem | GotRItems [RItem] | GotRBackground RBackground | GotRHoodle RHoodle | GotNone+ | FinishCommand SurfaceID deriving Show -- | @@ -123,15 +152,15 @@ | MenuRecentDocument | MenuLoadPNGorJPG | MenuLoadSVG+ | MenuLoadImageBackground | MenuText | MenuEmbedTextSource | MenuEditEmbedTextSource- | MenuEditNetEmbedTextSource | MenuTextFromSource | MenuLaTeX- | MenuLaTeXNetwork | MenuCombineLaTeX- | MenuLaTeXFromSource + | MenuLaTeXFromSource+ | MenuUpdateLaTeX | MenuEmbedPredefinedImage | MenuEmbedPredefinedImage2 | MenuEmbedPredefinedImage3 @@ -185,13 +214,10 @@ | MenuAddLink | MenuAddAnchor | MenuListAnchors- -- | MenuShapeRecognizer- -- | MenuRuler | MenuHandwritingRecognitionDialog | MenuSelectRegion | MenuSelectRectangle | MenuVerticalSpace- -- | MenuHandTool | MenuPenOptions | MenuEraserOptions | MenuHighlighterOptions@@ -202,10 +228,11 @@ | MenuDefaultHighlighter | MenuDefaultText | MenuSetAsDefaultOption+#ifdef DYRE | MenuRelaunch+#endif | MenuUseXInput | MenuUseTouch - | MenuSmoothScroll | MenuUsePopUpMenu | MenuEmbedImage | MenuEmbedPDF@@ -215,23 +242,19 @@ | MenuTogglePanZoomWidget | MenuToggleLayerWidget | MenuToggleClockWidget- | MenuDiscardCoreEvents - | MenuEraserTip + | MenuToggleScrollWidget | MenuPressureSensitivity- | MenuPageHighlight- | MenuMultiplePageView- | MenuMultiplePages- | MenuButton2Mapping- | MenuButton3Mapping - | MenuAntialiasedBitmaps- | MenuProgressiveBackgrounds- | MenuPrintPaperRuling - | MenuLeftHandedScrollbar- | MenuShortenMenus- | MenuAutoSavePreferences- | MenuSavePreferences+ | MenuAddTab+ | MenuCloseTab | MenuAbout | MenuDefault+#ifdef HUB+ | MenuEditNetEmbedTextSource+ | MenuToggleNetworkEditSource+ | MenuLaTeXNetwork+ | MenuHub+-- | MenuHubSocket+#endif deriving Show -- |@@ -251,8 +274,10 @@ | CMenuMakeLinkToAnchor Anchor | CMenuPangoConvert (Double,Double) T.Text | CMenuLaTeXConvert (Double,Double) T.Text+#ifdef HUB | CMenuLaTeXConvertNetwork (Double,Double) T.Text- | CMenuLaTeXUpdate (Double,Double) T.Text+#endif+ | CMenuLaTeXUpdate (Double,Double) Dimension T.Text | CMenuCropImage (BBoxed Image) | CMenuRotate RotateDir (BBoxed Image) | CMenuExport (BBoxed Image)@@ -263,19 +288,20 @@ -- | event for minibuffer operation (currently pen only) -data MiniBufferEvent = MiniBufferInitialized DrawWindow+data MiniBufferEvent = MiniBufferInitialized Gtk.DrawWindow | MiniBufferPenDown PenButton PointerCoord | MiniBufferPenUp PointerCoord | MiniBufferPenMove PointerCoord deriving Show -instance Show DrawWindow where+instance Show Gtk.DrawWindow where show _ = "DrawWindow" -- | event for multiline text view/buffer data MultiLineEvent = MultiLineChanged T.Text deriving Show +#ifdef HUB -- | event for network data NetworkEvent = NetworkDialog | NetworkInitialized ThreadId (MVar ())@@ -283,19 +309,22 @@ | NetworkCloseDialog | NetworkClosed deriving Show+#endif instance Show (MVar ()) where show _ = "MVar" +#ifdef HUB data DBusEvent = DBusNetworkInput T.Text | ImageFileDropped FilePath | GoToLink (T.Text,T.Text) deriving Show+#endif -- | -viewModeToUserEvent :: RadioAction -> IO UserEvent+viewModeToUserEvent :: Gtk.RadioAction -> IO UserEvent viewModeToUserEvent a = do - v <- radioActionGetCurrentValue a+ v <- Gtk.radioActionGetCurrentValue a case v of 1 -> return ToSinglePage 0 -> return ToContSinglePage
src/Hoodle/Type/HoodleState.hs view
@@ -1,12 +1,13 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TypeOperators #-} ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Type.HoodleState --- Copyright : (c) 2011-2014 Ian-Woo Kim+-- Copyright : (c) 2011-2015 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -14,24 +15,33 @@ ----------------------------------------------------------------------------- module Hoodle.Type.HoodleState -( HoodleState(..)+( HoodleState , HoodleModeState(..)+, UnitHoodle , IsOneTimeSelectMode(..)-, Settings(..)-, UIComponentSignalHandler(..)+, Settings+, UIComponentSignalHandler+, FileStore(..) -- | labels+, unitKey+, unitUUID+, unitButton , hoodleModeState , hoodleFileControl , cvsInfoMap , currentCanvas+, isOneTimeSelectMode , frameState , rootWindow+, unitHoodles+, rootNotebook , rootContainer , rootOfRootWindow , currentPenDraw , callBack , deviceList , penInfo+, cursorInfo , selectInfo , gtkUIManager , isSaved@@ -40,41 +50,49 @@ , isFullScreen , settings , uiComponentSignalHandler-, isOneTimeSelectMode , lastTimeCanvasConfigure , hookSet , tempLog , tempQueue , statusBar-, renderCache+, renderCacheVar , pdfRenderQueue+, genRenderQueue , doesNotInvalidate--- , cursorInfo+, nextPdfBkgPageNum -- , hoodleFileName , lastSavedTime+, syncMD5History -- , doesUseXInput , doesUseTouch-, doesSmoothScroll , doesUsePopUpMenu , doesEmbedImage , doesEmbedPDF , doesFollowLinks , doesKeepAspectRatio , doesUseVariableCursor+, newPageMode+, networkEditSourceInfo+#ifdef HUB+, sqliteFileName+#endif -- , penModeSignal , pageModeSignal , penPointSignal , penColorSignal+, newPageModeSignal+, switchTabSignal -- | others +, emptyUnitHoodle , emptyHoodleState , defaultSettings , defaultUIComponentSignalHandler , getHoodle -- | additional lenses -, getCanvasInfoMap +-- , getCanvasInfoMap , setCanvasInfoMap , getCurrentCanvasId , setCurrentCanvasId@@ -89,22 +107,22 @@ , getCurrentPageFromHoodleModeState , getCurrentPageDimFromHoodleModeState -- | for debug-, showCanvasInfoMapViewPortBBox+-- , showCanvasInfoMapViewPortBBox+-- , getTheUnit+-- , putTheUnit+, currentUnit ) where -import Control.Applicative hiding (empty) import Control.Concurrent import Control.Concurrent.STM-import Control.Lens (Simple,Lens,view,set,lens)-import Control.Monad.State hiding (get,modify)+import Control.Lens (Simple,Lens,view,set,lens,(^.)) import Data.Functor.Identity (Identity(..)) import qualified Data.HashMap.Strict as HM import qualified Data.IntMap as M-import Data.Maybe import Data.Sequence +import qualified Data.Text as T import Data.Time.Clock import Data.UUID (UUID)--- import qualified Graphics.Rendering.Cairo as Cairo import qualified Graphics.UI.Gtk as Gtk hiding (Clipboard, get,set) -- from hoodle-platform import Control.Monad.Trans.Crtn.Event @@ -139,72 +157,115 @@ | YesAfterSelect deriving (Show,Eq,Ord) +data UnitHoodle = UnitHoodle { _unitKey :: Int+ , _unitUUID :: UUID+ , _unitButton :: Gtk.Button+ , _hoodleModeState :: HoodleModeState+ , _hoodleFileControl :: HoodleFileControl+ , _cvsInfoMap :: CanvasInfoMap + , _currentCanvas :: (CanvasId,CanvasInfoBox)+ , _frameState :: WindowConfig + , _rootWindow :: Gtk.Widget+ , _rootContainer :: Gtk.Box+ , _isSaved :: Bool + , _undoTable :: UndoTable HoodleModeState+ , _isOneTimeSelectMode :: IsOneTimeSelectMode+ }++ data HoodleState = - HoodleState { _hoodleModeState :: HoodleModeState- , _hoodleFileControl :: HoodleFileControl- , _cvsInfoMap :: CanvasInfoMap - , _currentCanvas :: (CanvasId,CanvasInfoBox)- , _frameState :: WindowConfig - , _rootWindow :: Gtk.Widget- , _rootContainer :: Gtk.Box+ HoodleState { _unitHoodles :: (Int, M.IntMap UnitHoodle)+ , _rootNotebook :: Gtk.Notebook , _rootOfRootWindow :: Gtk.Window , _currentPenDraw :: PenDraw , _callBack :: AllEvent -> IO () , _deviceList :: DeviceList , _penInfo :: PenInfo+ , _cursorInfo :: (PenColor,Double,Bool) -- ^ (pen color, pen width, use variable cursor) , _selectInfo :: SelectInfo , _gtkUIManager :: Gtk.UIManager - , _isSaved :: Bool - , _undoTable :: UndoTable HoodleModeState- , _backgroundStyle :: BackgroundStyle , _isFullScreen :: Bool , _settings :: Settings + , _backgroundStyle :: BackgroundStyle , _uiComponentSignalHandler :: UIComponentSignalHandler - , _isOneTimeSelectMode :: IsOneTimeSelectMode , _lastTimeCanvasConfigure :: Maybe UTCTime , _hookSet :: Maybe Hook , _tempQueue :: Queue (Either (ActionOrder AllEvent) AllEvent) , _tempLog :: String -> String , _statusBar :: Maybe Gtk.Statusbar- , _renderCache :: RenderCache- , _pdfRenderQueue :: TVar (Seq (UUID,PDFCommand))+ , _renderCacheVar :: TVar RenderCache+ , _pdfRenderQueue :: PDFCommandQueue+ , _genRenderQueue :: GenCommandQueue , _doesNotInvalidate :: Bool- -- , _cursorInfo :: Maybe Cursor+ , _nextPdfBkgPageNum :: Maybe Int } --- | lens for hoodleModeState-hoodleModeState :: Simple Lens HoodleState HoodleModeState-hoodleModeState = lens _hoodleModeState (\f a -> f { _hoodleModeState = a } )+-- | current unit+currentUnit :: Simple Lens (Int,M.IntMap UnitHoodle) UnitHoodle+currentUnit = lens (\(k,m) -> fromJustError "currentUnit" (M.lookup k m)) (\(_,m) a -> (_unitKey a,M.insert (_unitKey a) a m)) +-- | lens for unitKey+unitKey :: Simple Lens UnitHoodle Int+unitKey = lens _unitKey (\f a -> f { _unitKey = a }) +-- | lens for unitKey+unitUUID :: Simple Lens UnitHoodle UUID+unitUUID = lens _unitUUID (\f a -> f { _unitUUID = a }) --- | -hoodleFileControl :: Simple Lens HoodleState HoodleFileControl-hoodleFileControl = lens _hoodleFileControl (\f a -> f { _hoodleFileControl = a })+-- | lens for unitKey+unitButton :: Simple Lens UnitHoodle Gtk.Button+unitButton = lens _unitButton (\f a -> f { _unitButton = a }) +-- | lens for hoodleModeState+hoodleModeState :: Simple Lens UnitHoodle HoodleModeState+hoodleModeState = lens _hoodleModeState (\f a -> f { _hoodleModeState = a } ) +-- | +hoodleFileControl :: Simple Lens UnitHoodle HoodleFileControl+hoodleFileControl = lens _hoodleFileControl (\f a -> f { _hoodleFileControl = a })+ -- | lens for cvsInfoMap-cvsInfoMap :: Simple Lens HoodleState CanvasInfoMap+cvsInfoMap :: Simple Lens UnitHoodle CanvasInfoMap cvsInfoMap = lens _cvsInfoMap (\f a -> f { _cvsInfoMap = a } ) -- | lens for currentCanvas-currentCanvas :: Simple Lens HoodleState (CanvasId,CanvasInfoBox)+currentCanvas :: Simple Lens UnitHoodle (CanvasId,CanvasInfoBox) currentCanvas = lens _currentCanvas (\f a -> f { _currentCanvas = a } ) -- | lens for frameState-frameState :: Simple Lens HoodleState WindowConfig+frameState :: Simple Lens UnitHoodle WindowConfig frameState = lens _frameState (\f a -> f { _frameState = a } ) -- | lens for rootWindow-rootWindow :: Simple Lens HoodleState Gtk.Widget+rootWindow :: Simple Lens UnitHoodle Gtk.Widget rootWindow = lens _rootWindow (\f a -> f { _rootWindow = a } ) -- | lens for rootContainer-rootContainer :: Simple Lens HoodleState Gtk.Box+rootContainer :: Simple Lens UnitHoodle Gtk.Box rootContainer = lens _rootContainer (\f a -> f { _rootContainer = a } ) +-- | lens for isSaved+isSaved :: Simple Lens UnitHoodle Bool+isSaved = lens _isSaved (\f a -> f { _isSaved = a } )++-- | lens for undoTable+undoTable :: Simple Lens UnitHoodle (UndoTable HoodleModeState)+undoTable = lens _undoTable (\f a -> f { _undoTable = a } )++-- | lens for isOneTimeSelectMode+isOneTimeSelectMode :: Simple Lens UnitHoodle IsOneTimeSelectMode+isOneTimeSelectMode = lens _isOneTimeSelectMode (\f a -> f { _isOneTimeSelectMode = a } )++-- | lens for unitHoodles +unitHoodles :: Simple Lens HoodleState (Int,M.IntMap UnitHoodle)+unitHoodles = lens _unitHoodles (\f a -> f { _unitHoodles = a } )++-- | lens for rootWindow+rootNotebook :: Simple Lens HoodleState Gtk.Notebook+rootNotebook = lens _rootNotebook (\f a -> f { _rootNotebook = a } )+ -- | lens for rootOfRootWindow rootOfRootWindow :: Simple Lens HoodleState Gtk.Window rootOfRootWindow = lens _rootOfRootWindow (\f a -> f { _rootOfRootWindow = a } )@@ -225,6 +286,11 @@ penInfo :: Simple Lens HoodleState PenInfo penInfo = lens _penInfo (\f a -> f { _penInfo = a } ) +-- | lens for cursorInfo+cursorInfo :: Simple Lens HoodleState (PenColor,Double,Bool)+cursorInfo = lens _cursorInfo (\f a -> f { _cursorInfo = a } )++ -- | lens for selectInfo selectInfo :: Simple Lens HoodleState SelectInfo selectInfo = lens _selectInfo (\f a -> f { _selectInfo = a } )@@ -233,14 +299,6 @@ gtkUIManager :: Simple Lens HoodleState Gtk.UIManager gtkUIManager = lens _gtkUIManager (\f a -> f { _gtkUIManager = a } ) --- | lens for isSaved-isSaved :: Simple Lens HoodleState Bool-isSaved = lens _isSaved (\f a -> f { _isSaved = a } )---- | lens for undoTable-undoTable :: Simple Lens HoodleState (UndoTable HoodleModeState)-undoTable = lens _undoTable (\f a -> f { _undoTable = a } )- -- | background style = plain, lined, ruled, graph backgroundStyle :: Simple Lens HoodleState BackgroundStyle backgroundStyle = lens _backgroundStyle (\f a -> f { _backgroundStyle = a } )@@ -257,12 +315,7 @@ uiComponentSignalHandler :: Simple Lens HoodleState UIComponentSignalHandler uiComponentSignalHandler = lens _uiComponentSignalHandler (\f a -> f { _uiComponentSignalHandler = a }) --- | lens for isOneTimeSelectMode-isOneTimeSelectMode :: Simple Lens HoodleState IsOneTimeSelectMode-isOneTimeSelectMode = lens _isOneTimeSelectMode (\f a -> f { _isOneTimeSelectMode = a } ) -- -- | lens for lastTimeCanvasConfigure lastTimeCanvasConfigure :: Simple Lens HoodleState (Maybe UTCTime) lastTimeCanvasConfigure = lens _lastTimeCanvasConfigure (\f a -> f { _lastTimeCanvasConfigure = a } )@@ -284,34 +337,46 @@ statusBar = lens _statusBar (\f a -> f { _statusBar = a }) -- | -renderCache :: Simple Lens HoodleState RenderCache-renderCache = lens _renderCache (\f a -> f { _renderCache = a })+renderCacheVar :: Simple Lens HoodleState (TVar RenderCache)+renderCacheVar = lens _renderCacheVar (\f a -> f { _renderCacheVar = a }) -- | -pdfRenderQueue :: Simple Lens HoodleState (TVar (Seq (UUID, PDFCommand)))+pdfRenderQueue :: Simple Lens HoodleState PDFCommandQueue pdfRenderQueue = lens _pdfRenderQueue (\f a -> f { _pdfRenderQueue = a }) +-- | +genRenderQueue :: Simple Lens HoodleState GenCommandQueue+genRenderQueue = lens _genRenderQueue (\f a -> f { _genRenderQueue = a }) + -- | doesNotInvalidate :: Simple Lens HoodleState Bool doesNotInvalidate = lens _doesNotInvalidate (\f a -> f { _doesNotInvalidate = a }) +-- | +nextPdfBkgPageNum :: Simple Lens HoodleState (Maybe Int)+nextPdfBkgPageNum = lens _nextPdfBkgPageNum (\f a -> f { _nextPdfBkgPageNum = a }) + {- -- | cursorInfo :: Simple Lens HoodleState (Maybe Cursor) cursorInfo = lens _cursorInfo (\f a -> f { _cursorInfo = a }) -} +data FileStore = LocalDir (Maybe FilePath)+ | TempDir FilePath+ -- | data HoodleFileControl = - HoodleFileControl { _hoodleFileName :: Maybe FilePath + HoodleFileControl { _hoodleFileName :: FileStore -- Maybe FilePath , _lastSavedTime :: Maybe UTCTime + , _syncMD5History :: [T.Text] } -- | lens for currFileName-hoodleFileName :: Simple Lens HoodleFileControl (Maybe FilePath)+hoodleFileName :: Simple Lens HoodleFileControl FileStore -- (Maybe FilePath) hoodleFileName = lens _hoodleFileName (\f a -> f { _hoodleFileName = a } ) -- | lens for last saved time@@ -319,13 +384,20 @@ lastSavedTime = lens _lastSavedTime (\f a -> f { _lastSavedTime = a } ) +-- | lens for last saved time+syncMD5History :: Simple Lens HoodleFileControl [T.Text] +syncMD5History = lens _syncMD5History (\f a -> f { _syncMD5History = a } ) ++ -- | data UIComponentSignalHandler = UIComponentSignalHandler { _penModeSignal :: Maybe (Gtk.ConnectId Gtk.RadioAction) , _pageModeSignal :: Maybe (Gtk.ConnectId Gtk.RadioAction) , _penPointSignal :: Maybe (Gtk.ConnectId Gtk.RadioAction) , _penColorSignal :: Maybe (Gtk.ConnectId Gtk.RadioAction)+ , _newPageModeSignal :: Maybe (Gtk.ConnectId Gtk.RadioAction)+ , _switchTabSignal :: Maybe (Gtk.ConnectId Gtk.Notebook) } -- | lens for penModeSignal@@ -344,18 +416,30 @@ penColorSignal :: Simple Lens UIComponentSignalHandler (Maybe (Gtk.ConnectId Gtk.RadioAction)) penColorSignal = lens _penColorSignal (\f a -> f { _penColorSignal = a } ) +-- | lens for newPageModeSignal+newPageModeSignal :: Simple Lens UIComponentSignalHandler (Maybe (Gtk.ConnectId Gtk.RadioAction))+newPageModeSignal = lens _newPageModeSignal (\f a -> f { _newPageModeSignal = a } ) +-- | lens for switchTabSignal+switchTabSignal :: Simple Lens UIComponentSignalHandler (Maybe (Gtk.ConnectId Gtk.Notebook))+switchTabSignal = lens _switchTabSignal (\f a -> f { _switchTabSignal = a } )++ -- | A set of Hoodle settings data Settings = Settings { _doesUseXInput :: Bool , _doesUseTouch :: Bool - , _doesSmoothScroll :: Bool , _doesUsePopUpMenu :: Bool , _doesEmbedImage :: Bool , _doesEmbedPDF :: Bool , _doesFollowLinks :: Bool , _doesKeepAspectRatio :: Bool , _doesUseVariableCursor :: Bool + , _newPageMode :: NewPageModeType+ , _networkEditSourceInfo :: Maybe ThreadId+#ifdef HUB+ , _sqliteFileName :: Maybe FilePath+#endif } @@ -367,10 +451,6 @@ doesUseTouch :: Simple Lens Settings Bool doesUseTouch = lens _doesUseTouch (\f a -> f { _doesUseTouch = a } ) --- | flag for smooth scrolling -doesSmoothScroll :: Simple Lens Settings Bool-doesSmoothScroll = lens _doesSmoothScroll (\f a -> f { _doesSmoothScroll = a } )- -- | flag for using popup menu doesUsePopUpMenu :: Simple Lens Settings Bool doesUsePopUpMenu = lens _doesUsePopUpMenu (\f a -> f { _doesUsePopUpMenu = a } )@@ -395,54 +475,83 @@ doesUseVariableCursor :: Simple Lens Settings Bool doesUseVariableCursor = lens _doesUseVariableCursor (\f a -> f {_doesUseVariableCursor=a}) +-- | new page mode: plain | last | cycle+newPageMode :: Simple Lens Settings NewPageModeType+newPageMode = lens _newPageMode (\f a -> f {_newPageMode=a})++-- | network edit source mode+networkEditSourceInfo :: Simple Lens Settings (Maybe ThreadId)+networkEditSourceInfo = lens _networkEditSourceInfo (\f a -> f {_networkEditSourceInfo=a})++#ifdef HUB+-- | sqlite file+sqliteFileName :: Simple Lens Settings (Maybe FilePath)+sqliteFileName = lens _sqliteFileName (\f a -> f {_sqliteFileName=a})+#endif++-- |+emptyUnitHoodle :: IO UnitHoodle+emptyUnitHoodle = do+ hdl <- emptyGHoodle+ return $ + UnitHoodle { _unitKey = 0+ , _unitUUID = error "unitUUID"+ , _unitButton = error "unitButton"+ , _hoodleModeState = ViewAppendState hdl + , _hoodleFileControl = emptyHoodleFileControl + , _cvsInfoMap = error "emptyHoodleState.cvsInfoMap"+ , _currentCanvas = error "emtpyHoodleState.currentCanvas"+ , _frameState = error "emptyHoodleState.frameState" + , _rootWindow = error "emtpyHoodleState.rootWindow"+ , _rootContainer = error "emptyHoodleState.rootContainer"+ , _isSaved = False + , _undoTable = emptyUndo 1 + , _isOneTimeSelectMode = NoOneTimeSelectMode+ }+ -- | default hoodle state emptyHoodleState :: IO HoodleState emptyHoodleState = do- hdl <- emptyGHoodle- tvar <- atomically $ newTVar empty + unit <- emptyUnitHoodle+ tvarpdf <- atomically $ newTVar empty + tvargen <- atomically $ newTVar empty + tvarcache <- atomically $ newTVar HM.empty return $- HoodleState - { _hoodleModeState = ViewAppendState hdl - , _hoodleFileControl = emptyHoodleFileControl - -- , _currFileName = Nothing - , _cvsInfoMap = error "emptyHoodleState.cvsInfoMap"- , _currentCanvas = error "emtpyHoodleState.currentCanvas"- , _frameState = error "emptyHoodleState.frameState" - , _rootWindow = error "emtpyHoodleState.rootWindow"- , _rootContainer = error "emptyHoodleState.rootContainer"- , _rootOfRootWindow = error "emptyHoodleState.rootOfRootWindow"- , _currentPenDraw = emptyPenDraw - -- , _clipboard = emptyClipboard- , _callBack = error "emtpyHoodleState.callBack"- , _deviceList = error "emtpyHoodleState.deviceList"- , _penInfo = defaultPenInfo - , _selectInfo = SelectInfo SelectLassoWork - , _gtkUIManager = error "emptyHoodleState.gtkUIManager"- , _isSaved = False - , _undoTable = emptyUndo 1 - -- , _isEventBlocked = False - , _backgroundStyle = BkgStyleLined- , _isFullScreen = False- , _settings = defaultSettings- , _uiComponentSignalHandler = defaultUIComponentSignalHandler - , _isOneTimeSelectMode = NoOneTimeSelectMode- -- , _pageModeSignal = Nothing- -- , _penModeSignal = Nothing - , _lastTimeCanvasConfigure = Nothing - , _hookSet = Nothing- , _tempQueue = emptyQueue- , _tempLog = id - , _statusBar = Nothing - , _renderCache = HM.empty- , _pdfRenderQueue = tvar- , _doesNotInvalidate = False- -- , _cursorInfo = Nothing- }+ HoodleState { _unitHoodles = (0, M.singleton 0 unit)+ , _rootNotebook = error "emtpyHoodleState.rootNotebook"+ , _rootOfRootWindow = error "emptyHoodleState.rootOfRootWindow"+ , _currentPenDraw = emptyPenDraw + , _callBack = error "emtpyHoodleState.callBack"+ , _deviceList = error "emtpyHoodleState.deviceList"+ , _penInfo = defaultPenInfo + , _cursorInfo = (defaultPenInfo ^. penSet.currPen.penColor, defaultPenInfo ^. penSet.currPen.penWidth, False)+ , _selectInfo = SelectInfo SelectLassoWork + , _gtkUIManager = error "emptyHoodleState.gtkUIManager"+ -- , _isEventBlocked = False + , _backgroundStyle = BkgStyleLined+ , _isFullScreen = False+ , _settings = defaultSettings+ , _uiComponentSignalHandler = defaultUIComponentSignalHandler + -- , _pageModeSignal = Nothing+ -- , _penModeSignal = Nothing + , _lastTimeCanvasConfigure = Nothing + , _hookSet = Nothing+ , _tempQueue = emptyQueue+ , _tempLog = id + , _statusBar = Nothing + , _renderCacheVar = tvarcache -- HM.empty+ , _pdfRenderQueue = tvarpdf+ , _genRenderQueue = tvargen+ , _doesNotInvalidate = False+ , _nextPdfBkgPageNum = Nothing+ -- , _cursorInfo = Nothing+ } emptyHoodleFileControl :: HoodleFileControl emptyHoodleFileControl = - HoodleFileControl { _hoodleFileName = Nothing + HoodleFileControl { _hoodleFileName = LocalDir Nothing , _lastSavedTime = Nothing + , _syncMD5History = [] } @@ -451,7 +560,9 @@ UIComponentSignalHandler{ _penModeSignal = Nothing , _pageModeSignal = Nothing , _penPointSignal = Nothing - , _penColorSignal = Nothing + , _penColorSignal = Nothing+ , _newPageModeSignal = Nothing+ , _switchTabSignal = Nothing } @@ -461,51 +572,48 @@ Settings { _doesUseXInput = False , _doesUseTouch = True- , _doesSmoothScroll = False , _doesUsePopUpMenu = True , _doesEmbedImage = True , _doesEmbedPDF = True , _doesFollowLinks = True , _doesKeepAspectRatio = False , _doesUseVariableCursor = False+ , _newPageMode = NPPlain+ , _networkEditSourceInfo = Nothing+#ifdef HUB+ , _sqliteFileName = Nothing+#endif } -- | -getHoodle :: HoodleState -> Hoodle EditMode +getHoodle :: UnitHoodle -> Hoodle EditMode getHoodle = either id gSelect2GHoodle . hoodleModeStateEither . view hoodleModeState -- | -getCurrentCanvasId :: HoodleState -> CanvasId+getCurrentCanvasId :: UnitHoodle -> CanvasId getCurrentCanvasId = fst . _currentCanvas -- | --setCurrentCanvasId :: CanvasId -> HoodleState -> Maybe HoodleState+setCurrentCanvasId :: CanvasId -> UnitHoodle -> Maybe UnitHoodle setCurrentCanvasId a f = do cinfobox <- M.lookup a (_cvsInfoMap f) return (f { _currentCanvas = (a,cinfobox) })- --- | - -getCanvasInfoMap :: HoodleState -> CanvasInfoMap -getCanvasInfoMap = _cvsInfoMap -- | --setCanvasInfoMap :: CanvasInfoMap -> HoodleState -> Maybe HoodleState -setCanvasInfoMap cmap xstate +setCanvasInfoMap :: CanvasInfoMap -> UnitHoodle -> Maybe UnitHoodle+setCanvasInfoMap cmap uhdl | M.null cmap = Nothing | otherwise = - let (cid,_) = _currentCanvas xstate+ let (cid,_) = _currentCanvas uhdl (cidmax,cinfomax) = M.findMax cmap mcinfobox = M.lookup cid cmap - in Just . maybe (xstate {_currentCanvas=(cidmax,cinfomax), _cvsInfoMap = cmap}) - (\cinfobox -> xstate {_currentCanvas = (cid,cinfobox)- ,_cvsInfoMap = cmap }) + in Just . maybe (uhdl {_currentCanvas=(cidmax,cinfomax), _cvsInfoMap = cmap}) + (\cinfobox -> uhdl { _currentCanvas = (cid,cinfobox)+ , _cvsInfoMap = cmap }) $ mcinfobox -currentCanvasInfo :: Simple Lens HoodleState CanvasInfoBox+currentCanvasInfo :: Simple Lens UnitHoodle CanvasInfoBox currentCanvasInfo = lens getter setter where getter = snd . _currentCanvas @@ -515,48 +623,47 @@ in f { _currentCanvas = (cid,a), _cvsInfoMap = cmap' } -- | -resetHoodleModeStateBuffers :: RenderCache -> HoodleModeState -> IO HoodleModeState -resetHoodleModeStateBuffers cache hdlmodestate1 = +resetHoodleModeStateBuffers :: CanvasId -> HoodleModeState -> Renderer ()+resetHoodleModeStateBuffers cid hdlmodestate1 = case hdlmodestate1 of - ViewAppendState hdl -> liftIO . liftM ViewAppendState . updateHoodleBuf cache $ hdl- _ -> return hdlmodestate1+ ViewAppendState hdl -> updateHoodleBuf cid hdl+ _ -> return () -- |-getCanvasInfo :: CanvasId -> HoodleState -> CanvasInfoBox -getCanvasInfo cid xstate = - let cinfoMap = getCanvasInfoMap xstate+getCanvasInfo :: CanvasId -> UnitHoodle -> CanvasInfoBox +getCanvasInfo cid uhdl = + let cinfoMap = view cvsInfoMap uhdl maybeCvs = M.lookup cid cinfoMap in maybeError' ("no canvas with id = " ++ show cid) maybeCvs -- | -setCanvasInfo :: (CanvasId,CanvasInfoBox) -> HoodleState -> HoodleState -setCanvasInfo (cid,cinfobox) xstate = - let cmap = getCanvasInfoMap xstate+setCanvasInfo :: (CanvasId,CanvasInfoBox) -> UnitHoodle -> UnitHoodle+setCanvasInfo (cid,cinfobox) uhdl = + let cmap = view cvsInfoMap uhdl cmap' = M.insert cid cinfobox cmap - in maybe xstate id $ setCanvasInfoMap cmap' xstate--+ in maybe uhdl id $ setCanvasInfoMap cmap' uhdl -- | change current canvas. this is the master function -updateFromCanvasInfoAsCurrentCanvas :: CanvasInfoBox -> HoodleState -> HoodleState-updateFromCanvasInfoAsCurrentCanvas cinfobox xstate = +updateFromCanvasInfoAsCurrentCanvas :: CanvasInfoBox -> UnitHoodle-> UnitHoodle+updateFromCanvasInfoAsCurrentCanvas cinfobox uhdl = let cid = view (unboxLens canvasId) cinfobox - cmap = getCanvasInfoMap xstate+ cmap = view cvsInfoMap uhdl cmap' = M.insert cid cinfobox cmap - in xstate { _currentCanvas = (cid,cinfobox)- , _cvsInfoMap = cmap' }+ in uhdl { _currentCanvas = (cid,cinfobox)+ , _cvsInfoMap = cmap' } -- | setCanvasId :: CanvasId -> CanvasInfoBox -> CanvasInfoBox setCanvasId cid = runIdentity . forBoth unboxBiXform (return . set canvasId cid) -- | -modifyCanvasInfo :: CanvasId -> (CanvasInfoBox -> CanvasInfoBox) -> HoodleState- -> HoodleState-modifyCanvasInfo cid f xstate = - maybe xstate id . flip setCanvasInfoMap xstate - . M.adjust f cid . getCanvasInfoMap - $ xstate +modifyCanvasInfo :: CanvasId -> (CanvasInfoBox -> CanvasInfoBox) + -> UnitHoodle+ -> UnitHoodle+modifyCanvasInfo cid f uhdl = + maybe uhdl id . flip setCanvasInfoMap uhdl+ . M.adjust f cid . view cvsInfoMap + $ uhdl -- | hoodleModeStateEither :: HoodleModeState -> Either (Hoodle EditMode) (Hoodle SelectMode) @@ -584,11 +691,6 @@ getPageMapFromHoodleModeState = either (view gpages) (view gselAll) . hoodleModeStateEither --- | -showCanvasInfoMapViewPortBBox :: HoodleState -> IO ()-showCanvasInfoMapViewPortBBox xstate = do - let cmap = getCanvasInfoMap xstate- print . map (view (unboxLens (viewInfo.pageArrangement.viewPortBBox))) . M.elems $ cmap
+ src/Hoodle/Type/Hub.hs view
@@ -0,0 +1,28 @@+-----------------------------------------------------------------------------+-- |+-- Module : Hoodle.Type.Hub+-- Copyright : (c) 2014 Ian-Woo Kim+--+-- License : BSD3+-- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>+-- Stability : experimental+-- Portability : GHC+--+-----------------------------------------------------------------------------++module Hoodle.Type.Hub where++import Data.Text (Text)+--+++data HubInfo = HubInfo { googleClientId :: Text+ , googleClientSecret :: Text+ , googleAuthURL :: String+ , hubURL :: String+ , hubFileRoot :: FilePath+ , hubSocketURL :: String+ , hubSocketPort :: Int+ , hubSocketPath :: String+ } + deriving (Show,Eq,Ord)
src/Hoodle/Type/PageArrangement.hs view
@@ -9,7 +9,7 @@ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Type.PageArrangement--- Copyright : (c) 2012, 2013 Ian-Woo Kim+-- Copyright : (c) 2012-2014 Ian-Woo Kim -- -- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>
+ src/Hoodle/Type/Synchronization.hs view
@@ -0,0 +1,105 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeFamilies #-}++-----------------------------------------------------------------------------+-- |+-- Module : Hoodle.Type.Synchronization+-- Copyright : (c) 2014, 2015 Ian-Woo Kim+--+-- License : BSD3+-- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>+-- Stability : experimental+-- Portability : GHC+--+-----------------------------------------------------------------------------++module Hoodle.Type.Synchronization where++import Control.Applicative+import Data.Aeson as AE+import Data.Data+import qualified Data.HashMap.Strict as H+import Data.Text+import Data.Time.Clock (UTCTime)+import Database.Persist.TH++share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|+FileSyncStatus+ uuid Text+ md5 Text+ time UTCTime+ UniqueFileSyncStatusUUID uuid+ deriving Typeable+ deriving Show+ deriving Eq+|]+++instance ToJSON FileSyncStatus where+ toJSON FileSyncStatus {..} = object [ "uuid" .= toJSON fileSyncStatusUuid + , "md5" .= toJSON fileSyncStatusMd5+ , "time" .= toJSON fileSyncStatusTime + ]+instance FromJSON FileSyncStatus where+ parseJSON (Object v) = + let r = do+ String uuid <- H.lookup "uuid" v+ String md5txt <- H.lookup "md5" v+ eutime <- fromJSON <$> H.lookup "time" v+ utime <- case eutime of+ Error _ -> Nothing+ Success a -> a+ return (FileSyncStatus uuid md5txt utime)+ in maybe (fail "error in parsing FileSyncStatus") return r+ parseJSON _ = fail "error in parsing FileSyncStatus" +++data FileContent = FileContent { file_uuid :: Text+ , file_path :: Maybe Text+ , file_content :: Text + , file_rsync :: Maybe FileRsync+ , client_uuid :: Text+ }+ deriving Show++instance ToJSON FileContent where+ toJSON FileContent {..} = object [ "uuid" .= toJSON file_uuid+ , "path" .= toJSON file_path+ , "content" .= toJSON file_content + , "rsync" .= toJSON file_rsync+ , "client" .= toJSON client_uuid+ ]++instance FromJSON FileContent where+ parseJSON (Object v) = + FileContent <$> v .: "uuid" + <*> v .: "path" + <*> v .: "content" + <*> v .: "rsync" + <*> v .: "client"+ parseJSON _ = fail "error in parsing FileContent"++data FileRsync = FileRsync { frsync_uuid :: Text + , frsync_sig :: Text+ }+ deriving Show++instance ToJSON FileRsync where+ toJSON FileRsync {..} = object [ "uuid" .= toJSON frsync_uuid+ , "signature" .= toJSON frsync_sig ]++instance FromJSON FileRsync where+ parseJSON (Object v) = + let r = do + String uuid <- H.lookup "uuid" v+ String sig <- H.lookup "signature" v+ return (FileRsync uuid sig)+ in maybe (fail "error in parsing FileRsync") return r+ parseJSON _ = fail "error in parsing FileRsync"
src/Hoodle/Type/Widget.hs view
@@ -20,6 +20,7 @@ , WidgetConfig , LayerWidgetConfig , ClockWidgetConfig+, ScrollWidgetConfig -- * lenses , panZoomWidgetPosition , panZoomWidgetTouchIsZoom@@ -30,13 +31,15 @@ , clockWidgetConfig , clockWidgetPosition , clockWidgetTime+, scrollWidgetConfig , widgetConfig , doesUsePanZoomWidget , doesUseLayerWidget , doesUseClockWidget+, doesUseScrollWidget -- * defaults , defaultCanvasWidgets-, defaultLWConfig +, defaultLWConfig , defaultWidgetConfig -- * utility , allWidgets@@ -48,12 +51,12 @@ -- | -data WidgetItem = PanZoomWidget | LayerWidget | ClockWidget +data WidgetItem = PanZoomWidget | LayerWidget | ClockWidget | ScrollWidget deriving (Show,Eq,Ord) -- | allWidgets :: [WidgetItem] -allWidgets = [PanZoomWidget, LayerWidget, ClockWidget] +allWidgets = [PanZoomWidget, LayerWidget, ClockWidget, ScrollWidget] -- | @@ -87,19 +90,24 @@ , _clockWidgetTime :: (Int,Int,Int) } - +-- | lens for position of clock widget clockWidgetPosition :: Simple Lens ClockWidgetConfig CanvasCoordinate clockWidgetPosition = lens _clockWidgetPosition (\f a -> f { _clockWidgetPosition = a } ) +-- | lens for time for clock widget clockWidgetTime :: Simple Lens ClockWidgetConfig (Int,Int,Int) clockWidgetTime = lens _clockWidgetTime (\f a -> f { _clockWidgetTime = a }) +-- |+data ScrollWidgetConfig = ScrWConfig + -- | data CanvasWidgets = CanvasWidgets { _panZoomWidgetConfig :: PanZoomWidgetConfig , _layerWidgetConfig :: LayerWidgetConfig - , _clockWidgetConfig :: ClockWidgetConfig + , _clockWidgetConfig :: ClockWidgetConfig+ , _scrollWidgetConfig :: ScrollWidgetConfig , _widgetConfig :: WidgetConfig } @@ -115,7 +123,11 @@ clockWidgetConfig :: Simple Lens CanvasWidgets ClockWidgetConfig clockWidgetConfig = lens _clockWidgetConfig (\f a -> f { _clockWidgetConfig = a }) +-- | +scrollWidgetConfig :: Simple Lens CanvasWidgets ScrollWidgetConfig+scrollWidgetConfig = lens _scrollWidgetConfig (\f a -> f { _scrollWidgetConfig = a }) + -- | default hoodle widgets defaultCanvasWidgets :: CanvasWidgets defaultCanvasWidgets = @@ -123,6 +135,7 @@ { _panZoomWidgetConfig = defaultPZWConfig , _layerWidgetConfig = defaultLWConfig , _clockWidgetConfig = defaultClkConfig+ , _scrollWidgetConfig = defaultScrWConfig , _widgetConfig = defaultWidgetConfig } @@ -147,9 +160,15 @@ } +-- | +defaultScrWConfig :: ScrollWidgetConfig +defaultScrWConfig = ScrWConfig++ data WidgetConfig = WidgetConfig { _doesUsePanZoomWidget :: Bool , _doesUseLayerWidget :: Bool - , _doesUseClockWidget :: Bool + , _doesUseClockWidget :: Bool+ , _doesUseScrollWidget :: Bool } -- | flag for pan zoom widget @@ -164,12 +183,17 @@ doesUseClockWidget :: Simple Lens WidgetConfig Bool doesUseClockWidget = lens _doesUseClockWidget (\f a -> f {_doesUseClockWidget = a}) +-- | flag for scroll widget+doesUseScrollWidget :: Simple Lens WidgetConfig Bool+doesUseScrollWidget = lens _doesUseScrollWidget (\f a -> f {_doesUseScrollWidget = a}) + -- | default widget configuration defaultWidgetConfig :: WidgetConfig defaultWidgetConfig = WidgetConfig { _doesUsePanZoomWidget = False , _doesUseLayerWidget = False , _doesUseClockWidget = False+ , _doesUseScrollWidget = False }
src/Hoodle/Util.hs view
@@ -3,7 +3,7 @@ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Util --- Copyright : (c) 2013 Ian-Woo Kim+-- Copyright : (c) 2013, 2014 Ian-Woo Kim -- -- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>@@ -15,7 +15,9 @@ module Hoodle.Util where import Control.Applicative -import Data.Attoparsec.Char8 +import Control.Monad.IO.Class+import Control.Monad.Trans.Maybe+import Data.Attoparsec.ByteString.Char8 import qualified Data.ByteString.Char8 as B import Data.Maybe import Data.Time.Clock @@ -36,16 +38,30 @@ (#) = flip ($) infixr 0 # +-- safehead :: [a] -> Maybe a+-- safehead [] = Nothing+-- safehead (a:_) = a+ maybeFlip :: Maybe a -> b -> (a->b) -> b maybeFlip m n j = maybe n j m -uncurry4 :: (a->b->c->d->e)->(a,b,c,d)->e -uncurry4 f (x,y,z,w) = f x y z w - maybeRead :: Read a => String -> Maybe a maybeRead = fmap fst . listToMaybe . reads +runMaybeT_ :: (Monad m) => MaybeT m a -> m ()+runMaybeT_ m = runMaybeT m >> return () +fromJustError :: String -> Maybe a -> a+fromJustError _ (Just x) = x+fromJustError err Nothing = error err++either_ :: (Monad m) => (b -> m ()) -> Either a b -> m ()+either_ = either (const (return ()))+++uncurry4 :: (a->b->c->d->e)->(a,b,c,d)->e +uncurry4 f (x,y,z,w) = f x y z w + getLargestWidth :: Hoodle -> Double getLargestWidth hdl = let ws = map (dim_width . page_dim) (hoodle_pages hdl) @@ -76,11 +92,15 @@ hPutStrLn outh str hClose outh ++-- | for debugging+msgShout :: (MonadIO m) => String -> m ()+msgShout = liftIO . putStrLn++ -- | maybeError' :: String -> Maybe a -> a maybeError' str = maybe (error str) id-- data UrlPath = FileUrl FilePath | HttpUrl String deriving (Show,Eq)
src/Hoodle/View/Coordinate.hs view
@@ -1,10 +1,11 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE TupleSections #-} ----------------------------------------------------------------------------- -- | -- Module : Hoodle.View.Coordinate--- Copyright : (c) 2012, 2013 Ian-Woo Kim+-- Copyright : (c) 2012-2014 Ian-Woo Kim -- -- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>@@ -22,7 +23,7 @@ import qualified Data.IntMap as M import Data.Maybe import Data.Monoid-import Graphics.UI.Gtk hiding (get,set)+import qualified Graphics.UI.Gtk as Gtk -- from hoodle-platform import Data.Hoodle.Simple (Dimension(..)) import Data.Hoodle.Generic@@ -50,18 +51,23 @@ , page2Desktop :: (PageNum,PageCoordinate) -> DesktopCoordinate } + -- | make a canvas geometry data structure from current status makeCanvasGeometry :: PageNum -> PageArrangement vm - -> DrawingArea + -> Gtk.DrawingArea -> IO CanvasGeometry makeCanvasGeometry cpn arr canvas = do - win <- widgetGetDrawWindow canvas+#ifdef GTK3 + Just win <- Gtk.widgetGetWindow canvas+#else+ win <- Gtk.widgetGetDrawWindow canvas+#endif let cdim@(CanvasDimension (Dim w' h')) = view canvasDimension arr- screen <- widgetGetScreen canvas- (ws,hs) <- (,) <$> (fromIntegral <$> screenGetWidth screen)- <*> (fromIntegral <$> screenGetHeight screen)- (x0,y0) <- return . ((,) <$> fromIntegral.fst <*> fromIntegral.snd ) =<< drawWindowGetOrigin win+ screen <- Gtk.widgetGetScreen canvas+ (ws,hs) <- (,) <$> (fromIntegral <$> Gtk.screenGetWidth screen)+ <*> (fromIntegral <$> Gtk.screenGetHeight screen)+ (x0,y0) <- return . ((,) <$> fromIntegral.fst <*> fromIntegral.snd ) =<< Gtk.drawWindowGetOrigin win let corig = CanvasOrigin (x0,y0) (deskdim, cvsvbbox, p2d, d2p) = case arr of
src/Hoodle/View/Draw.hs view
@@ -1,14 +1,15 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE Rank2Types #-} -{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE DataKinds #-}+{-# LANGUAGE TypeFamilies #-} ----------------------------------------------------------------------------- -- | -- Module : Hoodle.View.Draw --- Copyright : (c) 2011-2014 Ian-Woo Kim+-- Copyright : (c) 2011-2015 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -28,14 +29,14 @@ import Data.Monoid import Data.Sequence import qualified Graphics.Rendering.Cairo as Cairo-import Graphics.UI.Gtk hiding (get,set)+import qualified Graphics.UI.Gtk as Gtk -- from hoodle-platform import Data.Hoodle.BBox import Data.Hoodle.Generic import Data.Hoodle.Predefined import Data.Hoodle.Select import Data.Hoodle.Simple (Dimension(..),Stroke(..))-import Data.Hoodle.Zipper (currIndex,current)+import Data.Hoodle.Zipper (currIndex) import Graphics.Hoodle.Render import Graphics.Hoodle.Render.Generic import Graphics.Hoodle.Render.Highlight@@ -63,8 +64,9 @@ newtype SinglePageDraw a = SinglePageDraw { unSinglePageDraw :: RenderCache + -> CanvasId -> Bool -- ^ isCurrentCanvas- -> (DrawingArea, Maybe Cairo.Surface) + -> (Gtk.DrawingArea, Maybe Cairo.Surface) -> (PageNum, Page a) -> ViewInfo SinglePage -> Maybe BBox @@ -131,8 +133,16 @@ doubleBufferFlush :: Cairo.Surface -> CanvasInfo a -> IO () doubleBufferFlush sfc cinfo = do let canvas = view drawArea cinfo - win <- widgetGetDrawWindow canvas- renderWithDrawable win $ do +#ifdef GTK3+ Just win <- Gtk.widgetGetWindow canvas+#else + win <- Gtk.widgetGetDrawWindow canvas+#endif+#ifdef GTK3+ Gtk.renderWithDrawWindow win $ do +#else + Gtk.renderWithDrawable win $ do +#endif Cairo.setSourceSurface sfc 0 0 Cairo.setOperator Cairo.OperatorSource Cairo.paint@@ -140,11 +150,12 @@ -- | common routine for double buffering -doubleBufferDraw :: (DrawWindow, Maybe Cairo.Surface) - -> CanvasGeometry -> Cairo.Render () -> Cairo.Render a+doubleBufferDraw :: (Gtk.DrawWindow, Maybe Cairo.Surface) + -> CanvasGeometry + -> Cairo.Render a -> IntersectBBox -> IO (Maybe a)-doubleBufferDraw (win,msfc) geometry _xform rndr (Intersect ibbox) = do +doubleBufferDraw (win,msfc) geometry rndr (Intersect ibbox) = do let Dim cw ch = unCanvasDimension . canvasDim $ geometry mbbox' = case ibbox of Top -> Just (BBox (0,0) (cw,ch))@@ -153,7 +164,11 @@ let action = do case msfc of Nothing -> do - renderWithDrawable win $ do +#ifdef GTK3 + Gtk.renderWithDrawWindow win $ do+#else+ Gtk.renderWithDrawable win $ do +#endif clipBBox mbbox' Cairo.setSourceRGBA 0.5 0.5 0.5 1 Cairo.rectangle 0 0 cw ch @@ -167,7 +182,11 @@ Cairo.fill clipBBox mbbox' rndr - renderWithDrawable win $ do +#ifdef GTK3+ Gtk.renderWithDrawWindow win $ do+#else+ Gtk.renderWithDrawable win $ do +#endif Cairo.setSourceSurface sfc 0 0 Cairo.setOperator Cairo.OperatorSource Cairo.paint @@ -177,7 +196,7 @@ Middle _ -> Just <$> action Bottom -> return Nothing -+-- | mkXform4Page :: CanvasGeometry -> PageNum -> Xform4Page mkXform4Page geometry pnum = let CvsCoord (x0,y0) = desktop2Canvas geometry . page2Desktop geometry $ (pnum,PageCoord (0,0))@@ -186,27 +205,18 @@ sy = y1-y0 in Xform4Page x0 y0 sx sy - -- | cairoXform4PageCoordinate :: Xform4Page -> Cairo.Render () cairoXform4PageCoordinate xform = do Cairo.translate (transx xform) (transy xform) Cairo.scale (scalex xform) (scaley xform) - {- do - let CvsCoord (x0,y0) = desktop2Canvas geometry . page2Desktop geometry $ (pnum,PageCoord (0,0))- CvsCoord (x1,y1) = desktop2Canvas geometry . page2Desktop geometry $ (pnum,PageCoord (1,1))- sx = x1-x0 - sy = y1-y0- Cairo.translate x0 y0 - Cairo.scale sx sy--} -- | data PressureMode = NoPressure | Pressure -- | drawCurvebitGen :: PressureMode - -> DrawingArea+ -> Gtk.DrawingArea -> CanvasGeometry -> Double -> (Double,Double,Double,Double) @@ -216,9 +226,17 @@ -> ((Double,Double),Double) -> IO () drawCurvebitGen pmode canvas geometry wdth (r,g,b,a) pnum pdraw ((x0,y0),z0) ((x,y),z) = do - win <- widgetGetDrawWindow canvas- renderWithDrawable win $ do- cairoXform4PageCoordinate (mkXform4Page geometry pnum)+#ifdef GTK3 + Just win <- Gtk.widgetGetWindow canvas+#else + win <- Gtk.widgetGetDrawWindow canvas+#endif +#ifdef GTK3+ Gtk.renderWithDrawWindow win $ do +#else + Gtk.renderWithDrawable win $ do+#endif+ cairoXform4PageCoordinate (mkXform4Page geometry pnum) Cairo.setSourceRGBA r g b a case pmode of NoPressure -> do @@ -243,36 +261,40 @@ -- | drawFuncGen :: em - -> (RenderCache -> (PageNum,Page em) -> Maybe BBox + -> (RenderCache -> CanvasId -> (PageNum,Page em) -> Maybe BBox -> DrawFlag -> Cairo.Render (Page em)) -> DrawingFunction SinglePage em drawFuncGen _typ render = SinglePageDraw func - where func cache isCurrentCvs (canvas,msfc) (pnum,page) vinfo mbbox flag = do + where func cache cid isCurrentCvs (canvas,msfc) (pnum,page) vinfo mbbox flag = do let arr = view pageArrangement vinfo geometry <- makeCanvasGeometry pnum arr canvas- win <- widgetGetDrawWindow canvas+#ifdef GTK3 + Just win <- Gtk.widgetGetWindow canvas+#else+ win <- Gtk.widgetGetDrawWindow canvas+#endif let ibboxnew = getViewableBBox geometry mbbox let mbboxnew = toMaybe ibboxnew xformfunc = cairoXform4PageCoordinate (mkXform4Page geometry pnum) renderfunc = do xformfunc - pg <- render cache (pnum,page) mbboxnew flag+ pg <- render cache cid (pnum,page) mbboxnew flag -- Start Widget when isCurrentCvs (emphasisCanvasRender ColorBlue geometry) -- End Widget Cairo.resetClip return pg - doubleBufferDraw (win,msfc) geometry xformfunc renderfunc ibboxnew + doubleBufferDraw (win,msfc) geometry renderfunc ibboxnew >>= maybe (return page) return -- | -drawFuncSelGen :: (RenderCache -> (PageNum,Page SelectMode) -> Maybe BBox +drawFuncSelGen :: (RenderCache -> CanvasId -> (PageNum,Page SelectMode) -> Maybe BBox -> DrawFlag -> Cairo.Render ()) - -> (RenderCache -> (PageNum,Page SelectMode) -> Maybe BBox + -> (RenderCache -> CanvasId -> (PageNum,Page SelectMode) -> Maybe BBox -> DrawFlag -> Cairo.Render ()) -> DrawingFunction SinglePage SelectMode -drawFuncSelGen rencont rensel = drawFuncGen SelectMode (\c x y f -> rencont c x y f >> rensel c x y f >> return (snd x)) +drawFuncSelGen rencont rensel = drawFuncGen SelectMode (\c i x y f -> rencont c i x y f >> rensel c i x y f >> return (snd x)) -- | emphasisCanvasRender :: PenColor -> CanvasGeometry -> Cairo.Render ()@@ -312,14 +334,15 @@ -- |-drawContPageGen :: (RenderCache -> (PageNum,Page EditMode) -> Maybe BBox +drawContPageGen :: (RenderCache -> CanvasId -> (PageNum,Page EditMode) -> Maybe BBox -> DrawFlag -> Cairo.Render (Int,Page EditMode)) -> DrawingFunction ContinuousPage EditMode drawContPageGen render = ContPageDraw func where func :: RenderCache -> Bool -> CanvasInfo ContinuousPage -> Maybe BBox -> Hoodle EditMode -> DrawFlag -> IO (Hoodle EditMode) func cache isCurrentCvs cinfo mbbox hdl flag = do - let arr = view (viewInfo.pageArrangement) cinfo+ let cid = view canvasId cinfo+ arr = view (viewInfo.pageArrangement) cinfo pnum = PageNum . view currentPageNum $ cinfo canvas = view drawArea cinfo msfc = view mDrawSurface cinfo@@ -330,7 +353,11 @@ $ (getPagesInViewPortRange geometry hdl) where f k = maybe Nothing (\a->Just (k,a)) . M.lookup (unPageNum k) $ pgs- win <- widgetGetDrawWindow canvas+#ifdef GTK3 + Just win <- Gtk.widgetGetWindow canvas+#else+ win <- Gtk.widgetGetDrawWindow canvas+#endif let ibboxnew = getViewableBBox geometry mbbox let mbboxnew = toMaybe ibboxnew xformfunc = cairoXform4PageCoordinate (mkXform4Page geometry pnum)@@ -338,7 +365,7 @@ Cairo.identityMatrix cairoXform4PageCoordinate (mkXform4Page geometry pn) let pgmbbox = fmap (getBBoxInPageCoord geometry pn) mbboxnew- render cache (pn,pg) pgmbbox flag+ render cache cid (pn,pg) pgmbbox flag renderfunc = do xformfunc ndrawpgs <- mapM onepagerender drawpgs @@ -352,21 +379,22 @@ drawWidgets allWidgets hdl cinfo mbbox_canvas Cairo.resetClip return nhdl - doubleBufferDraw (win,msfc) geometry xformfunc renderfunc ibboxnew+ doubleBufferDraw (win,msfc) geometry renderfunc ibboxnew >>= maybe (return hdl) return -- |-drawContPageSelGen :: (RenderCache -> (PageNum,Page EditMode) -> Maybe BBox +drawContPageSelGen :: (RenderCache -> CanvasId -> (PageNum,Page EditMode) -> Maybe BBox -> DrawFlag -> Cairo.Render (Int,Page EditMode)) - -> (RenderCache -> (PageNum, Page SelectMode) -> Maybe BBox + -> (RenderCache -> CanvasId -> (PageNum, Page SelectMode) -> Maybe BBox -> DrawFlag -> Cairo.Render (Int,Page SelectMode)) -> DrawingFunction ContinuousPage SelectMode drawContPageSelGen rendergen rendersel = ContPageDraw func where func :: RenderCache -> Bool -> CanvasInfo ContinuousPage -> Maybe BBox -> Hoodle SelectMode ->DrawFlag -> IO (Hoodle SelectMode) func cache isCurrentCvs cinfo mbbox thdl flag = do - let arr = view (viewInfo.pageArrangement) cinfo+ let cid = view canvasId cinfo+ arr = view (viewInfo.pageArrangement) cinfo pnum = PageNum . view currentPageNum $ cinfo mtpage = view gselSelected thdl canvas = view drawArea cinfo @@ -379,21 +407,25 @@ $ (getPagesInViewPortRange geometry hdl) where f k = maybe Nothing (\a->Just (k,a)) . M.lookup (unPageNum k) $ pgs- win <- widgetGetDrawWindow canvas+#ifdef GTK3 + Just win <- Gtk.widgetGetWindow canvas+#else+ win <- Gtk.widgetGetDrawWindow canvas+#endif let ibboxnew = getViewableBBox geometry mbbox mbboxnew = toMaybe ibboxnew onepagerender (pn,pg) = do Cairo.identityMatrix let xform = mkXform4Page geometry pn cairoXform4PageCoordinate xform- rendergen cache (pn,pg) (fmap (getBBoxInPageCoord geometry pn) mbboxnew) flag+ rendergen cache cid (pn,pg) (fmap (getBBoxInPageCoord geometry pn) mbboxnew) flag selpagerender :: (PageNum, Page SelectMode) -> Cairo.Render (Int, Page SelectMode) selpagerender (pn,pg) = do Cairo.identityMatrix let xform = mkXform4Page geometry pn cairoXform4PageCoordinate xform - rendersel cache (pn,pg) (fmap (getBBoxInPageCoord geometry pn) mbboxnew) flag+ rendersel cache cid (pn,pg) (fmap (getBBoxInPageCoord geometry pn) mbboxnew) flag renderfunc :: Cairo.Render (Hoodle SelectMode) renderfunc = do let xform = mkXform4Page geometry pnum@@ -413,8 +445,7 @@ drawWidgets allWidgets hdl cinfo mbbox_canvas Cairo.resetClip return nthdl2 - doubleBufferDraw (win,msfc) geometry (cairoXform4PageCoordinate (mkXform4Page geometry pnum)) - renderfunc ibboxnew+ doubleBufferDraw (win,msfc) geometry renderfunc ibboxnew >>= maybe (return thdl) return @@ -422,28 +453,28 @@ drawSinglePage :: CanvasGeometry -> DrawingFunction SinglePage EditMode drawSinglePage geometry = drawFuncGen EditMode f where - f cache (pnum,page) mbbox flag = do + f cache cid (pnum,page) mbbox flag = do let xform = mkXform4Page geometry pnum case flag of- Clear -> do (pg',_) <- cairoRenderOption (RBkgDrawPDF,DrawFull) cache (page,Just xform) + Clear -> do (pg',_) <- cairoRenderOption (RBkgDrawPDF,DrawFull) cache cid (page,Just xform) return pg' - BkgEfficient -> do (InBBoxBkgBuf pg',_) <- cairoRenderOption (InBBoxOption mbbox) cache (InBBoxBkgBuf page, Just xform) + BkgEfficient -> do (InBBoxBkgBuf pg',_) <- cairoRenderOption (InBBoxOption mbbox) cache cid (InBBoxBkgBuf page, Just xform) return pg' - Efficient -> do (InBBox pg',_) <- cairoRenderOption (InBBoxOption mbbox) cache (InBBox page, Just xform)+ Efficient -> do (InBBox pg',_) <- cairoRenderOption (InBBoxOption mbbox) cache cid (InBBox page, Just xform) return pg' -- | drawSinglePageSel :: CanvasGeometry -> DrawingFunction SinglePage SelectMode drawSinglePageSel geometry = drawFuncSelGen rendercontent renderselect- where rendercontent cache (pnum,tpg) mbbox flag = do+ where rendercontent cache cid (pnum,tpg) mbbox flag = do let pg' = hPage2RPage tpg xform = mkXform4Page geometry pnum case flag of - Clear -> cairoRenderOption (RBkgDrawPDF,DrawFull) cache (pg',Just xform) >> return ()- BkgEfficient -> cairoRenderOption (InBBoxOption mbbox) cache (InBBoxBkgBuf pg',Just xform) >> return ()- Efficient -> cairoRenderOption (InBBoxOption mbbox) cache (InBBox pg',Just xform) >> return ()+ Clear -> cairoRenderOption (RBkgDrawPDF,DrawFull) cache cid (pg',Just xform) >> return ()+ BkgEfficient -> cairoRenderOption (InBBoxOption mbbox) cache cid (InBBoxBkgBuf pg',Just xform) >> return ()+ Efficient -> cairoRenderOption (InBBoxOption mbbox) cache cid (InBBox pg',Just xform) >> return () return ()- renderselect _cache (_pnum,tpg) mbbox _flag = do + renderselect _cache _cid (_pnum,tpg) mbbox _flag = do cairoHittedBoxDraw geometry tpg mbbox return () @@ -451,14 +482,14 @@ drawContHoodle :: CanvasGeometry -> DrawingFunction ContinuousPage EditMode drawContHoodle geometry = drawContPageGen f where - f cache (pnum@(PageNum n),page) mbbox flag = do + f cache cid (pnum@(PageNum n),page) mbbox flag = do let xform = mkXform4Page geometry pnum case flag of- Clear -> do (p',_) <- cairoRenderOption (RBkgDrawPDF,DrawFull) cache (page, Just xform) + Clear -> do (p',_) <- cairoRenderOption (RBkgDrawPDF,DrawFull) cache cid (page, Just xform) return (n, p')- BkgEfficient -> do (p',_) <- cairoRenderOption (InBBoxOption mbbox) cache (InBBoxBkgBuf page, Just xform)+ BkgEfficient -> do (p',_) <- cairoRenderOption (InBBoxOption mbbox) cache cid (InBBoxBkgBuf page, Just xform) return (n, unInBBoxBkgBuf p')- Efficient -> do (p',_) <- cairoRenderOption (InBBoxOption mbbox) cache (InBBox page, Just xform)+ Efficient -> do (p',_) <- cairoRenderOption (InBBoxOption mbbox) cache cid (InBBox page, Just xform) return (n, unInBBox p') @@ -466,13 +497,13 @@ drawContHoodleSel :: CanvasGeometry -> DrawingFunction ContinuousPage SelectMode drawContHoodleSel geometry = drawContPageSelGen renderother renderselect - where renderother cache (pnum@(PageNum n),page) mbbox flag = do+ where renderother cache cid (pnum@(PageNum n),page) mbbox flag = do let xform = mkXform4Page geometry pnum case flag of - Clear -> (,) n . fst <$> cairoRenderOption (RBkgDrawPDF,DrawFull) cache (page,Just xform) - BkgEfficient -> (,) n . unInBBoxBkgBuf . fst <$> cairoRenderOption (InBBoxOption mbbox) cache (InBBoxBkgBuf page,Just xform)- Efficient -> (,) n . unInBBox . fst <$> cairoRenderOption (InBBoxOption mbbox) cache (InBBox page,Just xform)- renderselect _cache (PageNum n,tpg) mbbox _flag = do+ Clear -> (,) n . fst <$> cairoRenderOption (RBkgDrawPDF,DrawFull) cache cid (page,Just xform) + BkgEfficient -> (,) n . unInBBoxBkgBuf . fst <$> cairoRenderOption (InBBoxOption mbbox) cache cid (InBBoxBkgBuf page,Just xform)+ Efficient -> (,) n . unInBBox . fst <$> cairoRenderOption (InBBoxOption mbbox) cache cid (InBBox page,Just xform)+ renderselect _cache _cid (PageNum n,tpg) mbbox _flag = do cairoHittedBoxDraw geometry tpg mbbox return (n,tpg) @@ -587,11 +618,12 @@ -- | canvasImageSurface :: RenderCache+ -> CanvasId -> Maybe Double -- ^ multiply -> CanvasGeometry -> Hoodle EditMode -> IO (Cairo.Surface,Dimension)-canvasImageSurface cache mmulti geometry hdl = do +canvasImageSurface cache cid mmulti geometry hdl = do let ViewPortBBox bbx_desk = getCanvasViewPort geometry nbbx_desk = case mmulti of Nothing -> bbx_desk @@ -615,7 +647,7 @@ Cairo.translate (z*ws_cvs) (z*hs_cvs) let xform = mkXform4Page geometry pn cairoXform4PageCoordinate xform- cairoRenderOption (InBBoxOption Nothing) cache (InBBox pg,Nothing :: Maybe Xform4Page) -- Just xform+ cairoRenderOption (InBBoxOption Nothing) cache cid (InBBox pg, Nothing :: Maybe Xform4Page) renderfunc = do Cairo.setSourceRGBA 0.5 0.5 0.5 1 Cairo.rectangle 0 0 w_cvs h_cvs @@ -646,8 +678,11 @@ when (ClockWidget `elem` witms && view (canvasWidgets.widgetConfig.doesUseClockWidget) cinfo) $ renderClockWidget mbbox (view (canvasWidgets.clockWidgetConfig) cinfo) + when (ScrollWidget `elem` witms && view (canvasWidgets.widgetConfig.doesUseScrollWidget) cinfo) $+ renderScrollWidget mbbox (view (canvasWidgets.scrollWidgetConfig) cinfo) + --------------------- -- Pan Zoom Widget -- ---------------------@@ -698,12 +733,12 @@ pg <- MaybeT . return $ view (gpages.at cpn) hdl let lyrs = view glayers pg n = currIndex lyrs - l = current lyrs - LyBuf msfc = view gbuffer l+ -- l = current lyrs lift $ renderLayerWidget (show n) mbbox cvscoord when (view layerWidgetShowContent lc) $ do - sfc <- MaybeT . return $ msfc - lift $ renderLayerContent mbbox (view gdimension pg) sfc cvscoord+ liftIO $ putStrLn "drawLayerWidget: not implemented"+ -- sfc <- MaybeT . return $ msfc + -- lift $ renderLayerContent mbbox (view gdimension pg) sfc cvscoord return () renderLayerContent :: Maybe BBox @@ -763,28 +798,28 @@ Cairo.fill -- Cairo.identityMatrix - l1 <- createLayout "layer"- updateLayout l1 - (_,reclog) <- liftIO $ layoutGetExtents l1- let PangoRectangle _ _ w1 h1 = reclog + l1 <- Gtk.createLayout "layer"+ Gtk.updateLayout l1 + (_,reclog) <- liftIO $ Gtk.layoutGetExtents l1+ let Gtk.PangoRectangle _ _ w1 h1 = reclog Cairo.moveTo (x+15) y let sx1 = 50 / w1 sy1 = 20 / h1 Cairo.scale sx1 sy1 - layoutPath l1+ Gtk.layoutPath l1 Cairo.setSourceRGBA 0 0 0 0.4 Cairo.fill -- Cairo.identityMatrix- l <- createLayout str - updateLayout l - (_,reclog2) <- liftIO $ layoutGetExtents l- let PangoRectangle _ _ w h = reclog2 + l <- Gtk.createLayout str + Gtk.updateLayout l + (_,reclog2) <- liftIO $ Gtk.layoutGetExtents l+ let Gtk.PangoRectangle _ _ w h = reclog2 Cairo.moveTo (x+30) (y+20) let sx = 40 / w sy = 60 / h Cairo.scale sx sy - layoutPath l + Gtk.layoutPath l Cairo.setSourceRGBA 0 0 0 0.4 Cairo.fill @@ -822,6 +857,24 @@ Cairo.lineTo (x+30*sin (div2rad 12 h + div2rad 720 m)) (y-30*cos (div2rad 12 h + div2rad 720 m)) Cairo.stroke+ -- + Cairo.resetClip ++++------------------+-- Clock Widget --+------------------++renderScrollWidget :: Maybe BBox -> ScrollWidgetConfig -> Cairo.Render () +renderScrollWidget mbbox _cfg = do + Cairo.identityMatrix + clipBBox mbbox + Cairo.setSourceRGBA 0.5 0.5 0.2 0.3 + Cairo.moveTo 100 0+ Cairo.lineTo 0 50 + Cairo.lineTo 200 50 + Cairo.fill -- Cairo.resetClip
src/Hoodle/Widget/Clock.hs view
@@ -1,9 +1,9 @@ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Widget.Clock--- Copyright : (c) 2013, 2014 Ian-Woo Kim+-- Copyright : (c) 2013-2015 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -14,7 +14,7 @@ module Hoodle.Widget.Clock where -import Control.Lens (view,set,over)+import Control.Lens (view,set,over,(.~)) import Control.Monad.State import Data.Functor.Identity (Identity(..)) import Data.List (delete)@@ -25,6 +25,7 @@ import Data.Hoodle.Simple import Graphics.Hoodle.Render.Util.HitTest --+import Hoodle.Accessor import Hoodle.Coroutine.Draw import Hoodle.Coroutine.Pen import Hoodle.Device@@ -62,11 +63,13 @@ startClockWidget :: (CanvasId,CanvasInfo a,CanvasGeometry) -> CWAction -> MainCoroutine () -startClockWidget (cid,cinfo,geometry) (Move (oxy,owxy)) = do +startClockWidget (_cid,cinfo,geometry) (Move (oxy,owxy)) = do xst <- get - let hdl = getHoodle xst- cache = view renderCache xst- (srcsfc,Dim wsfc hsfc) <- liftIO (canvasImageSurface cache Nothing geometry hdl)+ cache <- renderCache+ let uhdl = view (unitHoodles.currentUnit) xst+ hdl = getHoodle uhdl+ cid = getCurrentCanvasId uhdl+ (srcsfc,Dim wsfc hsfc) <- liftIO (canvasImageSurface cache cid Nothing geometry hdl) -- need to draw other widgets here let otherwidgets = delete ClockWidget allWidgets liftIO $ Cairo.renderWith srcsfc (drawWidgets otherwidgets hdl cinfo Nothing) @@ -107,24 +110,26 @@ -> MainCoroutine () moveClockWidget cid geometry (srcsfc,tgtsfc) (CvsCoord (xw,yw)) (CvsCoord (x0,y0)) pcoord = do let CvsCoord (x,y) = (desktop2Canvas geometry . device2Desktop geometry) pcoord - xst <- get - let CanvasDimension (Dim cw ch) = canvasDim geometry - cinfobox = getCanvasInfo cid xst - nposx | xw+x-x0 < -50 = -50 - | xw+x-x0 > cw-50 = cw-50 - | otherwise = xw+x-x0- nposy | yw+y-y0 < -50 = -50 - | yw+y-y0 > ch-50 = ch-50 - | otherwise = yw+y-y0 - nwpos = CvsCoord (nposx,nposy) - changeact :: CanvasInfo a -> CanvasInfo a - changeact cinfo = - set (canvasWidgets.clockWidgetConfig.clockWidgetPosition) nwpos $ cinfo- ncinfobox = (runIdentity . forBoth unboxBiXform (return . changeact)) cinfobox- put (setCanvasInfo (cid,ncinfobox) xst)+ modify $ \xst -> + let uhdl = view (unitHoodles.currentUnit) xst+ CanvasDimension (Dim cw ch) = canvasDim geometry + cinfobox = getCanvasInfo cid uhdl+ nposx | xw+x-x0 < -50 = -50 + | xw+x-x0 > cw-50 = cw-50 + | otherwise = xw+x-x0+ nposy | yw+y-y0 < -50 = -50 + | yw+y-y0 > ch-50 = ch-50 + | otherwise = yw+y-y0 + nwpos = CvsCoord (nposx,nposy) + changeact :: CanvasInfo a -> CanvasInfo a + changeact cinfo = + set (canvasWidgets.clockWidgetConfig.clockWidgetPosition) nwpos $ cinfo+ ncinfobox = (runIdentity . forBoth unboxBiXform (return . changeact)) cinfobox+ in (unitHoodles.currentUnit .~ (setCanvasInfo (cid,ncinfobox) uhdl)) xst -- xst2 <- get - let cinfobox2 = getCanvasInfo cid xst2 + let uhdl = view (unitHoodles.currentUnit) xst2+ cinfobox2 = getCanvasInfo cid uhdl cfg = view (unboxLens (canvasWidgets.clockWidgetConfig)) cinfobox2 liftIO $ forBoth' unboxBiAct (\cinfo-> virtualDoubleBufferDraw srcsfc tgtsfc (return ()) (renderClockWidget Nothing cfg) @@ -133,9 +138,10 @@ -- | toggleClock :: CanvasId -> MainCoroutine () toggleClock cid = do - modify (\xst -> - let ncinfobox = (over (unboxLens (canvasWidgets.widgetConfig.doesUseClockWidget)) not - . getCanvasInfo cid ) xst - in setCanvasInfo (cid,ncinfobox) xst)+ modify $ \xst ->+ let uhdl = view (unitHoodles.currentUnit) xst+ ncinfobox = (over (unboxLens (canvasWidgets.widgetConfig.doesUseClockWidget)) not + . getCanvasInfo cid ) uhdl+ in (unitHoodles.currentUnit .~ (setCanvasInfo (cid,ncinfobox) uhdl)) xst invalidateInBBox Nothing Efficient cid
src/Hoodle/Widget/Dispatch.hs view
@@ -7,7 +7,7 @@ -- Module : Hoodle.Widget.Dispatch -- Copyright : (c) 2011-2014 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -21,25 +21,22 @@ import Control.Monad.State hiding (forM_) import Control.Monad.Trans.Maybe import qualified Data.ByteString.Char8 as B+import qualified Data.Text.Encoding as TE import Data.Foldable (forM_)----- +-- import Data.Hoodle.BBox import Data.Hoodle.Simple import Graphics.Hoodle.Render.Util.HitTest import Graphics.Hoodle.Render.Type.Item -- +import Hoodle.Coroutine.Link import Hoodle.Device -import Hoodle.ModelAction.ContextMenu import Hoodle.Type.Canvas import Hoodle.Type.Coroutine import Hoodle.Type.HoodleState- import Hoodle.Type.PageArrangement import Hoodle.Util import Hoodle.View.Coordinate - import Hoodle.Widget.Clock import Hoodle.Widget.Layer import Hoodle.Widget.PanZoom@@ -48,7 +45,8 @@ -> PointerCoord -> MainCoroutine () -- ^ default action -> MainCoroutine ()-widgetCheckPen cid pcoord defact = get >>= \xst -> forBoth' unboxBiAct (chk xst) (getCanvasInfo cid xst) +widgetCheckPen cid pcoord defact = + get >>= \xst -> forBoth' unboxBiAct (chk xst) ((getCanvasInfo cid . view (unitHoodles.currentUnit)) xst) where chk :: HoodleState -> CanvasInfo a -> MainCoroutine () chk xstate cinfo = do @@ -74,12 +72,9 @@ let lnk = bbxed_content lnkbbx loc = link_location lnk mid = case lnk of - LinkAnchor {..} -> Just (link_linkeddocid,link_anchorid)+ LinkAnchor {..} -> Just (TE.decodeUtf8 link_linkeddocid,TE.decodeUtf8 link_anchorid) _ -> Nothing-- forM_ - ((urlParse . B.unpack) loc)- (\url -> liftIO (openLinkAction url mid))+ forM_ ((urlParse . B.unpack) loc) (\url -> lift (openLinkAction url mid)) MaybeT (return (Just ())) _ -> MaybeT (return Nothing)) case m of
src/Hoodle/Widget/Layer.hs view
@@ -1,9 +1,9 @@ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Widget.Layer--- Copyright : (c) 2013, 2014 Ian-Woo Kim+-- Copyright : (c) 2013-2015 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -14,7 +14,7 @@ module Hoodle.Widget.Layer where -import Control.Lens (view,set,over)+import Control.Lens (view,set,over,(.~)) import Control.Monad.State import Data.Functor.Identity (Identity(..)) import Data.List (delete)@@ -26,6 +26,7 @@ import Data.Hoodle.Simple import Graphics.Hoodle.Render.Util.HitTest --+import Hoodle.Accessor import Hoodle.Coroutine.Draw import Hoodle.Coroutine.Layer import Hoodle.Coroutine.Pen@@ -67,14 +68,15 @@ -> MainCoroutine () startLayerWidget (cid,_cinfo,_geometry) Close = toggleLayer cid startLayerWidget (cid,_cinfo,_geometry) ToggleShowContent = do - liftIO $ putStrLn "ToggleShowContent hitted"- modify (over (currentCanvasInfo . unboxLens (canvasWidgets.layerWidgetConfig.layerWidgetShowContent)) not)+ modify $ over (unitHoodles.currentUnit)+ $ over (currentCanvasInfo . unboxLens (canvasWidgets.layerWidgetConfig.layerWidgetShowContent)) not invalidate cid startLayerWidget (cid,cinfo,geometry) (Move (oxy,owxy)) = do xst <- get - let hdl = getHoodle xst- cache = view renderCache xst- (srcsfc,Dim wsfc hsfc) <- liftIO (canvasImageSurface cache Nothing geometry hdl)+ cache <- renderCache+ let uhdl = view (unitHoodles.currentUnit) xst+ hdl = getHoodle uhdl+ (srcsfc,Dim wsfc hsfc) <- liftIO (canvasImageSurface cache cid Nothing geometry hdl) -- need to draw other widgets here let otherwidgets = delete LayerWidget allWidgets liftIO $ Cairo.renderWith srcsfc (drawWidgets otherwidgets hdl cinfo Nothing) @@ -121,34 +123,36 @@ -> MainCoroutine () moveLayerWidget cid geometry (srcsfc,tgtsfc) (CvsCoord (xw,yw)) (CvsCoord (x0,y0)) pcoord = do let CvsCoord (x,y) = (desktop2Canvas geometry . device2Desktop geometry) pcoord - xst <- get - let CanvasDimension (Dim cw ch) = canvasDim geometry - cinfobox = getCanvasInfo cid xst - nposx | xw+x-x0 < -50 = -50 - | xw+x-x0 > cw-50 = cw-50 - | otherwise = xw+x-x0- nposy | yw+y-y0 < -50 = -50 - | yw+y-y0 > ch-50 = ch-50 - | otherwise = yw+y-y0 - nwpos = CvsCoord (nposx,nposy) - changeact :: CanvasInfo a -> CanvasInfo a - changeact cinfo = - set (canvasWidgets.layerWidgetConfig.layerWidgetPosition) nwpos $ cinfo- ncinfobox = (runIdentity . forBoth unboxBiXform (return . changeact)) cinfobox- put (setCanvasInfo (cid,ncinfobox) xst)- let hdl = getHoodle xst - -- - xst2 <- get - let cinfobox2 = getCanvasInfo cid xst2 - liftIO $ forBoth' unboxBiAct (\cinfo-> virtualDoubleBufferDraw srcsfc tgtsfc (return ()) - (drawLayerWidget hdl cinfo Nothing nwpos) - >> doubleBufferFlush tgtsfc cinfo) cinfobox2+ get >>= \xst -> do+ let uhdl = view (unitHoodles.currentUnit) xst+ CanvasDimension (Dim cw ch) = canvasDim geometry + cinfobox = getCanvasInfo cid uhdl+ nposx | xw+x-x0 < -50 = -50 + | xw+x-x0 > cw-50 = cw-50 + | otherwise = xw+x-x0+ nposy | yw+y-y0 < -50 = -50 + | yw+y-y0 > ch-50 = ch-50 + | otherwise = yw+y-y0 + nwpos = CvsCoord (nposx,nposy) + changeact :: CanvasInfo a -> CanvasInfo a + changeact cinfo = + set (canvasWidgets.layerWidgetConfig.layerWidgetPosition) nwpos $ cinfo+ ncinfobox = (runIdentity . forBoth unboxBiXform (return . changeact)) cinfobox+ put $ (unitHoodles.currentUnit .~ setCanvasInfo (cid,ncinfobox) uhdl) xst+ -- + xst2 <- get + let uhdl2 = view (unitHoodles.currentUnit) xst2+ hdl2 = getHoodle uhdl2+ cinfobox2 = getCanvasInfo cid uhdl2+ liftIO $ forBoth' unboxBiAct (\cinfo-> virtualDoubleBufferDraw srcsfc tgtsfc (return ()) + (drawLayerWidget hdl2 cinfo Nothing nwpos) + >> doubleBufferFlush tgtsfc cinfo) cinfobox2 -- | toggleLayer :: CanvasId -> MainCoroutine () toggleLayer cid = do - modify (\xst -> - let ncinfobox = (over (unboxLens (canvasWidgets.widgetConfig.doesUseLayerWidget)) not - . getCanvasInfo cid ) xst - in setCanvasInfo (cid,ncinfobox) xst)- invalidateInBBox Nothing Efficient cid+ pureUpdateUhdl $ \uhdl -> + let ncinfobox = (over (unboxLens (canvasWidgets.widgetConfig.doesUseLayerWidget)) not + . getCanvasInfo cid ) uhdl+ in setCanvasInfo (cid,ncinfobox) uhdl+ invalidateInBBox Nothing Efficient cid
src/Hoodle/Widget/PanZoom.hs view
@@ -1,9 +1,11 @@+{-# LANGUAGE MultiWayIf #-}+ ----------------------------------------------------------------------------- -- | -- Module : Hoodle.Widget.PanZoom--- Copyright : (c) 2013, 2014 Ian-Woo Kim+-- Copyright : (c) 2013-2015 Ian-Woo Kim ----- License : GPL-3+-- License : BSD3 -- Maintainer : Ian-Woo Kim <ianwookim@gmail.com> -- Stability : experimental -- Portability : GHC@@ -15,6 +17,7 @@ module Hoodle.Widget.PanZoom where -- from other packages+import Control.Applicative import Control.Lens (view,set,over,(.~)) import Control.Monad.Identity import Control.Monad.State @@ -84,15 +87,15 @@ startPanZoomWidget tchmode (cid,cinfo,geometry) mmode = do modify (doesNotInvalidate .~ True) xst <- get - let hdl = getHoodle xst- cache = view renderCache xst+ cache <- renderCache+ let hdl = (getHoodle . view (unitHoodles.currentUnit)) xst case mmode of Nothing -> togglePanZoom cid Just (mode,(oxy,owxy)) -> do (srcsfc,Dim wsfc hsfc) <- case mode of - Moving -> liftIO (canvasImageSurface cache Nothing geometry hdl)- Zooming -> liftIO (canvasImageSurface cache (Just 1) geometry hdl)- Panning _ -> liftIO (canvasImageSurface cache (Just 1) geometry hdl) + Moving -> liftIO (canvasImageSurface cache cid Nothing geometry hdl)+ Zooming -> liftIO (canvasImageSurface cache cid (Just 1) geometry hdl)+ Panning _ -> liftIO (canvasImageSurface cache cid (Just 1) geometry hdl) -- need to draw other widgets here let otherwidgets = delete PanZoomWidget allWidgets liftIO $ Cairo.renderWith @@ -114,16 +117,10 @@ -> (Double,(Double,Double)) findZoomXform (Dim w h) ((xo,yo),(x0,_y0),(x,_y)) = let tx = x - x0 - -- ty = y - y0 ztx = 1 + tx / 200- -- zty = 1 + ty / 200 zx | ztx > 2 = 2 | ztx < 0.5 = 0.5 | otherwise = ztx- -- zy | zty > 2 = 2 - -- | zty < 0.5 = 0.5- -- | otherwise = zty - -- simplified z = zx xtrans = (1 -z)*xo/z-w ytrans = (1- z)*yo/z-h @@ -187,19 +184,20 @@ case mpnpgxy of Nothing -> return () Just pnpgxy -> do - xstate <- get- geom' <- liftIO $ getCanvasGeometryCvsId cid xstate+ uhdl <- view (unitHoodles.currentUnit) <$> get+ geom' <- liftIO $ getCanvasGeometryCvsId cid uhdl let DeskCoord (xd,yd) = page2Desktop geom' pnpgxy DeskCoord (xd0,yd0) = canvas2Desktop geom' ccoord - moveViewPortBy (return ()) cid - (\(xorig,yorig)->(xorig+xd-xd0,yorig+yd-yd0)) + moveViewPortBy (return ()) cid (\(xorig,yorig)->(xorig+xd-xd0,yorig+yd-yd0)) Panning _ -> do let (x_d,y_d) = (unDeskCoord . device2Desktop geometry) pcoord (x0_d,y0_d) = (unDeskCoord . canvas2Desktop geometry) (CvsCoord (x0,y0))- (dx_d,dy_d) = (x_d-x0_d,y_d-y0_d)- moveViewPortBy (return ()) cid - (\(xorig,yorig)->(xorig-dx_d,yorig-dy_d)) + (dx_d,dy_d) = let (dx_d1,dy_d1) = (x_d-x0_d,y_d-y0_d)+ in if | abs dx_d1 < 25 -> (0,dy_d1)+ | abs dy_d1 < 25 -> (dx_d1,0)+ | otherwise -> (dx_d1,dy_d1)+ moveViewPortBy (return ()) cid (\(xorig,yorig)->(xorig-dx_d,yorig-dy_d)) _ -> return () invalidate cid @@ -212,11 +210,11 @@ -> MainCoroutine () movingRender mode cid geometry (srcsfc,tgtsfc) (CvsCoord (xw,yw)) (CvsCoord (x0,y0)) pcoord = do let CvsCoord (x,y) = (desktop2Canvas geometry . device2Desktop geometry) pcoord - xst <- get + uhdl <- view (unitHoodles.currentUnit) <$> get case mode of Moving -> do let CanvasDimension (Dim cw ch) = canvasDim geometry - cinfobox = getCanvasInfo cid xst + cinfobox = getCanvasInfo cid uhdl nposx | xw+x-x0 < -50 = -50 | xw+x-x0 > cw-50 = cw-50 | otherwise = xw+x-x0@@ -228,21 +226,21 @@ changeact cinfo = set (canvasWidgets.panZoomWidgetConfig.panZoomWidgetPosition) nwpos $ cinfo ncinfobox = (runIdentity . forBoth unboxBiXform (return.changeact)) cinfobox- isTouchZoom = view (unboxLens (canvasWidgets.panZoomWidgetConfig.panZoomWidgetTouchIsZoom)) cinfobox - put (setCanvasInfo (cid,ncinfobox) xst)+ isTouchZoom = view (unboxLens (canvasWidgets.panZoomWidgetConfig.panZoomWidgetTouchIsZoom)) cinfobox+ pureUpdateUhdl $ setCanvasInfo (cid,ncinfobox) virtualDoubleBufferDraw srcsfc tgtsfc (return ()) (renderPanZoomWidget isTouchZoom Nothing nwpos) Zooming -> do - let cinfobox = getCanvasInfo cid xst + let cinfobox = getCanvasInfo cid uhdl let pos = runIdentity (forBoth' unboxBiAct (return.view (canvasWidgets.panZoomWidgetConfig.panZoomWidgetPosition)) cinfobox) let (xo,yo) = (xw+50,yw+50) CanvasDimension cdim = canvasDim geometry (z,(xtrans,ytrans)) = findZoomXform cdim ((xo,yo),(x0,y0),(x,y))- isTouchZoom = view (unboxLens (canvasWidgets.panZoomWidgetConfig.panZoomWidgetTouchIsZoom)) cinfobox + isTouchZoom = view (unboxLens (canvasWidgets.panZoomWidgetConfig.panZoomWidgetTouchIsZoom)) cinfobox virtualDoubleBufferDraw srcsfc tgtsfc (Cairo.save >> Cairo.scale z z >> Cairo.translate xtrans ytrans) (Cairo.restore >> renderPanZoomWidget isTouchZoom Nothing pos) Panning b -> do - let cinfobox = getCanvasInfo cid xst + let cinfobox = getCanvasInfo cid uhdl CanvasDimension cdim = canvasDim geometry (xtrans,ytrans) = findPanXform cdim ((x0,y0),(x,y)) let CanvasDimension (Dim cw ch) = canvasDim geometry @@ -258,29 +256,29 @@ runIdentity (forBoth' unboxBiAct (return.view (canvasWidgets.panZoomWidgetConfig.panZoomWidgetPosition)) cinfobox) ncinfobox = set (unboxLens (canvasWidgets.panZoomWidgetConfig.panZoomWidgetPosition)) nwpos cinfobox isTouchZoom = view (unboxLens (canvasWidgets.panZoomWidgetConfig.panZoomWidgetTouchIsZoom)) cinfobox - put (setCanvasInfo (cid,ncinfobox) xst)+ pureUpdateUhdl $ setCanvasInfo (cid,ncinfobox) virtualDoubleBufferDraw srcsfc tgtsfc (Cairo.save >> Cairo.translate xtrans ytrans) (Cairo.restore >> renderPanZoomWidget isTouchZoom Nothing nwpos) -- xst2 <- get - let cinfobox = getCanvasInfo cid xst2 + let cinfobox = getCanvasInfo cid . view (unitHoodles.currentUnit) $ xst2 liftIO $ forBoth' unboxBiAct (doubleBufferFlush tgtsfc) cinfobox -- | togglePanZoom :: CanvasId -> MainCoroutine () togglePanZoom cid = do - modify $ \xst -> - let cinfobox = getCanvasInfo cid xst + pureUpdateUhdl $ \uhdl -> + let cinfobox = getCanvasInfo cid uhdl ncinfobox = over (unboxLens (canvasWidgets.widgetConfig.doesUsePanZoomWidget)) not cinfobox- in setCanvasInfo (cid,ncinfobox) xst + in setCanvasInfo (cid,ncinfobox) uhdl invalidateInBBox Nothing Efficient cid -- | touchStart :: CanvasId -> PointerCoord -> MainCoroutine () -touchStart cid pcoord = forBoth' unboxBiAct chk =<< liftM (getCanvasInfo cid) get+touchStart cid pcoord = forBoth' unboxBiAct chk =<< (getCanvasInfo cid . view (unitHoodles.currentUnit) <$> get) where chk :: CanvasInfo a -> MainCoroutine () chk cinfo = do @@ -293,13 +291,13 @@ CvsCoord (x0,y0) = view (canvasWidgets.panZoomWidgetConfig.panZoomWidgetPosition) cinfo obbox = BBox (x0,y0) (x0+100,y0+100) xst <- get- if (isPointInBBox obbox (x,y)) then do - let changeact :: CanvasInfo a -> CanvasInfo a - changeact = over (canvasWidgets.panZoomWidgetConfig.panZoomWidgetTouchIsZoom) not - ncinfobox = runIdentity . forBoth unboxBiXform (return . changeact) . getCanvasInfo cid $ xst- put (setCanvasInfo (cid,ncinfobox) xst)+ pureUpdateUhdl $ \uhdl -> + let changeact :: CanvasInfo a -> CanvasInfo a + changeact = over (canvasWidgets.panZoomWidgetConfig.panZoomWidgetTouchIsZoom) not + ncinfobox = runIdentity . forBoth unboxBiXform (return . changeact) . getCanvasInfo cid $ uhdl+ in setCanvasInfo (cid,ncinfobox) uhdl invalidateInBBox Nothing Efficient cid else do let b = view (settings.doesUseTouch) xst@@ -310,7 +308,7 @@ else do let devlst = view deviceList xst doIOaction $ \_ -> do- setToggleUIForFlag "HANDA" (settings.doesUseTouch) xst+ lensSetToggleUIForFlag "HANDA" (settings.doesUseTouch) xst -- ad hoc let touchstr = dev_touch_str devlst when (touchstr /= "touch") $ do @@ -326,16 +324,16 @@ updateFlagFromToggleUI "HANDA" (settings.doesUseTouch) xst <- get let devlst = view deviceList xst - let b = view (settings.doesUseTouch) xst- when b $ do + uhdl = view (unitHoodles.currentUnit) xst+ (cid,_cinfobox) = view currentCanvas uhdl+ when (view (settings.doesUseTouch) xst) $ do -- ad hoc let touchstr = dev_touch_str devlst when (touchstr /= "touch") $ do liftIO $ readProcess "xinput" [ "enable", dev_touch_str devlst ] "" return () --- let (cid,_cinfobox) = view currentCanvas xst - put (set (currentCanvasInfo. unboxLens (canvasWidgets.widgetConfig.doesUsePanZoomWidget)) True xst)+ pureUpdateUhdl $ (currentCanvasInfo. unboxLens (canvasWidgets.widgetConfig.doesUsePanZoomWidget)) .~ True invalidateInBBox Nothing Efficient cid return ()
+ src/Hoodle/Widget/Scroll.hs view
@@ -0,0 +1,36 @@+-----------------------------------------------------------------------------+-- |+-- Module : Hoodle.Widget.Scroll+-- Copyright : (c) 2014 Ian-Woo Kim+--+-- License : BSD3+-- Maintainer : Ian-Woo Kim <ianwookim@gmail.com>+-- Stability : experimental+-- Portability : GHC+--+-- Pan-Zoom widget drawing and action+-- +-----------------------------------------------------------------------------++module Hoodle.Widget.Scroll where++import Control.Lens ((%~))+--+import Hoodle.Accessor+import Hoodle.Coroutine.Draw+import Hoodle.Type.Canvas+import Hoodle.Type.Coroutine+import Hoodle.Type.Enum+import Hoodle.Type.HoodleState+import Hoodle.Type.Widget+++-- | +toggleScroll :: CanvasId -> MainCoroutine () +toggleScroll cid = do + pureUpdateUhdl $ \uhdl -> + let ncinfobox = + ( (unboxLens (canvasWidgets.widgetConfig.doesUseScrollWidget) %~ not)+ . getCanvasInfo cid ) uhdl + in setCanvasInfo (cid,ncinfobox) uhdl+ invalidateInBBox Nothing Efficient cid