summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGustavo Sverzut Barbieri <barbieri@profusion.mobi>2013-11-13 18:57:28 -0200
committerGustavo Sverzut Barbieri <barbieri@profusion.mobi>2013-11-13 18:57:28 -0200
commit3e5e849e3047583ef438d0c1df3f927a4d289d3b (patch)
treef7d0e9f1a19498cfda2cfb4bcfd285aad3763613
Initial Commit
-rw-r--r--.gitignore28
-rw-r--r--AUTHORS1
-rw-r--r--COPYING339
-rw-r--r--Makefile.am75
-rw-r--r--README79
-rwxr-xr-xautogen.sh16
-rw-r--r--configure.ac91
-rw-r--r--data/desktop/eruler.desktop10
-rw-r--r--data/icons/eruler.pngbin0 -> 5968 bytes
-rw-r--r--data/themes/default.edc1668
-rw-r--r--m4/ac_attribute.m447
-rw-r--r--m4/efl_binary.m471
-rw-r--r--src/bin/main.c2663
-rw-r--r--src/bin/platform-x.c556
-rw-r--r--src/bin/private.h46
15 files changed, 5690 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6c2d170
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,28 @@
1*.o
2.deps
3.dirstamp
4aclocal.m4
5autom4te.cache
6compile
7config.h
8config.h.in
9config.log
10config.status
11configure
12data/themes/*.edj
13depcomp
14eruler-*.tar.bz2
15eruler-*.tar.gz
16INSTALL
17install-sh
18ltmain.sh
19m4/libtool.m4
20m4/ltoptions.m4
21m4/ltsugar.m4
22m4/ltversion.m4
23m4/lt~obsolete.m4
24Makefile
25Makefile.in
26missing
27src/bin/eruler
28stamp-h1
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..818d7af
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
Gustavo Sverzut Barbieri <barbieri@gmail.com>
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..d159169
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
1 GNU GENERAL PUBLIC LICENSE
2 Version 2, June 1991
3
4 Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 Everyone is permitted to copy and distribute verbatim copies
7 of this license document, but changing it is not allowed.
8
9 Preamble
10
11 The licenses for most software are designed to take away your
12freedom to share and change it. By contrast, the GNU General Public
13License is intended to guarantee your freedom to share and change free
14software--to make sure the software is free for all its users. This
15General Public License applies to most of the Free Software
16Foundation's software and to any other program whose authors commit to
17using it. (Some other Free Software Foundation software is covered by
18the GNU Lesser General Public License instead.) You can apply it to
19your programs, too.
20
21 When we speak of free software, we are referring to freedom, not
22price. Our General Public Licenses are designed to make sure that you
23have the freedom to distribute copies of free software (and charge for
24this service if you wish), that you receive source code or can get it
25if you want it, that you can change the software or use pieces of it
26in new free programs; and that you know you can do these things.
27
28 To protect your rights, we need to make restrictions that forbid
29anyone to deny you these rights or to ask you to surrender the rights.
30These restrictions translate to certain responsibilities for you if you
31distribute copies of the software, or if you modify it.
32
33 For example, if you distribute copies of such a program, whether
34gratis or for a fee, you must give the recipients all the rights that
35you have. You must make sure that they, too, receive or can get the
36source code. And you must show them these terms so they know their
37rights.
38
39 We protect your rights with two steps: (1) copyright the software, and
40(2) offer you this license which gives you legal permission to copy,
41distribute and/or modify the software.
42
43 Also, for each author's protection and ours, we want to make certain
44that everyone understands that there is no warranty for this free
45software. If the software is modified by someone else and passed on, we
46want its recipients to know that what they have is not the original, so
47that any problems introduced by others will not reflect on the original
48authors' reputations.
49
50 Finally, any free program is threatened constantly by software
51patents. We wish to avoid the danger that redistributors of a free
52program will individually obtain patent licenses, in effect making the
53program proprietary. To prevent this, we have made it clear that any
54patent must be licensed for everyone's free use or not licensed at all.
55
56 The precise terms and conditions for copying, distribution and
57modification follow.
58
59 GNU GENERAL PUBLIC LICENSE
60 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
62 0. This License applies to any program or other work which contains
63a notice placed by the copyright holder saying it may be distributed
64under the terms of this General Public License. The "Program", below,
65refers to any such program or work, and a "work based on the Program"
66means either the Program or any derivative work under copyright law:
67that is to say, a work containing the Program or a portion of it,
68either verbatim or with modifications and/or translated into another
69language. (Hereinafter, translation is included without limitation in
70the term "modification".) Each licensee is addressed as "you".
71
72Activities other than copying, distribution and modification are not
73covered by this License; they are outside its scope. The act of
74running the Program is not restricted, and the output from the Program
75is covered only if its contents constitute a work based on the
76Program (independent of having been made by running the Program).
77Whether that is true depends on what the Program does.
78
79 1. You may copy and distribute verbatim copies of the Program's
80source code as you receive it, in any medium, provided that you
81conspicuously and appropriately publish on each copy an appropriate
82copyright notice and disclaimer of warranty; keep intact all the
83notices that refer to this License and to the absence of any warranty;
84and give any other recipients of the Program a copy of this License
85along with the Program.
86
87You may charge a fee for the physical act of transferring a copy, and
88you may at your option offer warranty protection in exchange for a fee.
89
90 2. You may modify your copy or copies of the Program or any portion
91of it, thus forming a work based on the Program, and copy and
92distribute such modifications or work under the terms of Section 1
93above, provided that you also meet all of these conditions:
94
95 a) You must cause the modified files to carry prominent notices
96 stating that you changed the files and the date of any change.
97
98 b) You must cause any work that you distribute or publish, that in
99 whole or in part contains or is derived from the Program or any
100 part thereof, to be licensed as a whole at no charge to all third
101 parties under the terms of this License.
102
103 c) If the modified program normally reads commands interactively
104 when run, you must cause it, when started running for such
105 interactive use in the most ordinary way, to print or display an
106 announcement including an appropriate copyright notice and a
107 notice that there is no warranty (or else, saying that you provide
108 a warranty) and that users may redistribute the program under
109 these conditions, and telling the user how to view a copy of this
110 License. (Exception: if the Program itself is interactive but
111 does not normally print such an announcement, your work based on
112 the Program is not required to print an announcement.)
113
114These requirements apply to the modified work as a whole. If
115identifiable sections of that work are not derived from the Program,
116and can be reasonably considered independent and separate works in
117themselves, then this License, and its terms, do not apply to those
118sections when you distribute them as separate works. But when you
119distribute the same sections as part of a whole which is a work based
120on the Program, the distribution of the whole must be on the terms of
121this License, whose permissions for other licensees extend to the
122entire whole, and thus to each and every part regardless of who wrote it.
123
124Thus, it is not the intent of this section to claim rights or contest
125your rights to work written entirely by you; rather, the intent is to
126exercise the right to control the distribution of derivative or
127collective works based on the Program.
128
129In addition, mere aggregation of another work not based on the Program
130with the Program (or with a work based on the Program) on a volume of
131a storage or distribution medium does not bring the other work under
132the scope of this License.
133
134 3. You may copy and distribute the Program (or a work based on it,
135under Section 2) in object code or executable form under the terms of
136Sections 1 and 2 above provided that you also do one of the following:
137
138 a) Accompany it with the complete corresponding machine-readable
139 source code, which must be distributed under the terms of Sections
140 1 and 2 above on a medium customarily used for software interchange; or,
141
142 b) Accompany it with a written offer, valid for at least three
143 years, to give any third party, for a charge no more than your
144 cost of physically performing source distribution, a complete
145 machine-readable copy of the corresponding source code, to be
146 distributed under the terms of Sections 1 and 2 above on a medium
147 customarily used for software interchange; or,
148
149 c) Accompany it with the information you received as to the offer
150 to distribute corresponding source code. (This alternative is
151 allowed only for noncommercial distribution and only if you
152 received the program in object code or executable form with such
153 an offer, in accord with Subsection b above.)
154
155The source code for a work means the preferred form of the work for
156making modifications to it. For an executable work, complete source
157code means all the source code for all modules it contains, plus any
158associated interface definition files, plus the scripts used to
159control compilation and installation of the executable. However, as a
160special exception, the source code distributed need not include
161anything that is normally distributed (in either source or binary
162form) with the major components (compiler, kernel, and so on) of the
163operating system on which the executable runs, unless that component
164itself accompanies the executable.
165
166If distribution of executable or object code is made by offering
167access to copy from a designated place, then offering equivalent
168access to copy the source code from the same place counts as
169distribution of the source code, even though third parties are not
170compelled to copy the source along with the object code.
171
172 4. You may not copy, modify, sublicense, or distribute the Program
173except as expressly provided under this License. Any attempt
174otherwise to copy, modify, sublicense or distribute the Program is
175void, and will automatically terminate your rights under this License.
176However, parties who have received copies, or rights, from you under
177this License will not have their licenses terminated so long as such
178parties remain in full compliance.
179
180 5. You are not required to accept this License, since you have not
181signed it. However, nothing else grants you permission to modify or
182distribute the Program or its derivative works. These actions are
183prohibited by law if you do not accept this License. Therefore, by
184modifying or distributing the Program (or any work based on the
185Program), you indicate your acceptance of this License to do so, and
186all its terms and conditions for copying, distributing or modifying
187the Program or works based on it.
188
189 6. Each time you redistribute the Program (or any work based on the
190Program), the recipient automatically receives a license from the
191original licensor to copy, distribute or modify the Program subject to
192these terms and conditions. You may not impose any further
193restrictions on the recipients' exercise of the rights granted herein.
194You are not responsible for enforcing compliance by third parties to
195this License.
196
197 7. If, as a consequence of a court judgment or allegation of patent
198infringement or for any other reason (not limited to patent issues),
199conditions are imposed on you (whether by court order, agreement or
200otherwise) that contradict the conditions of this License, they do not
201excuse you from the conditions of this License. If you cannot
202distribute so as to satisfy simultaneously your obligations under this
203License and any other pertinent obligations, then as a consequence you
204may not distribute the Program at all. For example, if a patent
205license would not permit royalty-free redistribution of the Program by
206all those who receive copies directly or indirectly through you, then
207the only way you could satisfy both it and this License would be to
208refrain entirely from distribution of the Program.
209
210If any portion of this section is held invalid or unenforceable under
211any particular circumstance, the balance of the section is intended to
212apply and the section as a whole is intended to apply in other
213circumstances.
214
215It is not the purpose of this section to induce you to infringe any
216patents or other property right claims or to contest validity of any
217such claims; this section has the sole purpose of protecting the
218integrity of the free software distribution system, which is
219implemented by public license practices. Many people have made
220generous contributions to the wide range of software distributed
221through that system in reliance on consistent application of that
222system; it is up to the author/donor to decide if he or she is willing
223to distribute software through any other system and a licensee cannot
224impose that choice.
225
226This section is intended to make thoroughly clear what is believed to
227be a consequence of the rest of this License.
228
229 8. If the distribution and/or use of the Program is restricted in
230certain countries either by patents or by copyrighted interfaces, the
231original copyright holder who places the Program under this License
232may add an explicit geographical distribution limitation excluding
233those countries, so that distribution is permitted only in or among
234countries not thus excluded. In such case, this License incorporates
235the limitation as if written in the body of this License.
236
237 9. The Free Software Foundation may publish revised and/or new versions
238of the General Public License from time to time. Such new versions will
239be similar in spirit to the present version, but may differ in detail to
240address new problems or concerns.
241
242Each version is given a distinguishing version number. If the Program
243specifies a version number of this License which applies to it and "any
244later version", you have the option of following the terms and conditions
245either of that version or of any later version published by the Free
246Software Foundation. If the Program does not specify a version number of
247this License, you may choose any version ever published by the Free Software
248Foundation.
249
250 10. If you wish to incorporate parts of the Program into other free
251programs whose distribution conditions are different, write to the author
252to ask for permission. For software which is copyrighted by the Free
253Software Foundation, write to the Free Software Foundation; we sometimes
254make exceptions for this. Our decision will be guided by the two goals
255of preserving the free status of all derivatives of our free software and
256of promoting the sharing and reuse of software generally.
257
258 NO WARRANTY
259
260 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268REPAIR OR CORRECTION.
269
270 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278POSSIBILITY OF SUCH DAMAGES.
279
280 END OF TERMS AND CONDITIONS
281
282 How to Apply These Terms to Your New Programs
283
284 If you develop a new program, and you want it to be of the greatest
285possible use to the public, the best way to achieve this is to make it
286free software which everyone can redistribute and change under these terms.
287
288 To do so, attach the following notices to the program. It is safest
289to attach them to the start of each source file to most effectively
290convey the exclusion of warranty; and each file should have at least
291the "copyright" line and a pointer to where the full notice is found.
292
293 <one line to give the program's name and a brief idea of what it does.>
294 Copyright (C) <year> <name of author>
295
296 This program is free software; you can redistribute it and/or modify
297 it under the terms of the GNU General Public License as published by
298 the Free Software Foundation; either version 2 of the License, or
299 (at your option) any later version.
300
301 This program is distributed in the hope that it will be useful,
302 but WITHOUT ANY WARRANTY; without even the implied warranty of
303 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 GNU General Public License for more details.
305
306 You should have received a copy of the GNU General Public License along
307 with this program; if not, write to the Free Software Foundation, Inc.,
308 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309
310Also add information on how to contact you by electronic and paper mail.
311
312If the program is interactive, make it output a short notice like this
313when it starts in an interactive mode:
314
315 Gnomovision version 69, Copyright (C) year name of author
316 Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 This is free software, and you are welcome to redistribute it
318 under certain conditions; type `show c' for details.
319
320The hypothetical commands `show w' and `show c' should show the appropriate
321parts of the General Public License. Of course, the commands you use may
322be called something other than `show w' and `show c'; they could even be
323mouse-clicks or menu items--whatever suits your program.
324
325You should also get your employer (if you work as a programmer) or your
326school, if any, to sign a "copyright disclaimer" for the program, if
327necessary. Here is a sample; alter the names:
328
329 Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 `Gnomovision' (which makes passes at compilers) written by James Hacker.
331
332 <signature of Ty Coon>, 1 April 1989
333 Ty Coon, President of Vice
334
335This General Public License does not permit incorporating your program into
336proprietary programs. If your program is a subroutine library, you may
337consider it more useful to permit linking proprietary applications with the
338library. If this is what you want to do, use the GNU Lesser General
339Public License instead of this License.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..8ae6881
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,75 @@
1ACLOCAL_AMFLAGS = -I m4
2
3MAINTAINERCLEANFILES = \
4Makefile.in \
5$(PACKAGE_TARNAME)-$(PACKAGE_VERSION).tar.gz \
6$(PACKAGE_TARNAME)-$(PACKAGE_VERSION).tar.bz2 \
7aclocal.m4 \
8config.guess \
9config.h.in \
10config.sub \
11configure \
12compile \
13depcomp \
14install-sh \
15ltconfig \
16ltmain.sh \
17missing \
18mkinstalldirs \
19stamp-h.in \
20stamp-h \
21m4/libtool.m4 \
22m4/lt~obsolete.m4 \
23m4/ltoptions.m4 \
24m4/ltsugar.m4 \
25m4/ltversion.m4
26
27bin_PROGRAMS = src/bin/eruler
28
29src_bin_eruler_SOURCES = \
30src/bin/main.c \
31src/bin/private.h
32
33if HAVE_ECORE_X
34src_bin_eruler_SOURCES += src/bin/platform-x.c
35endif
36
37src_bin_eruler_LDADD = @ERULER_LIBS@
38src_bin_eruler_CPPFLAGS = \
39-I$(top_builddir) \
40-DPACKAGE_BIN_DIR=\"$(bindir)\" \
41-DPACKAGE_DATA_DIR=\"$(pkgdatadir)\" \
42@ERULER_CFLAGS@
43
44desktopdir = $(datadir)/applications
45desktop_DATA = data/desktop/eruler.desktop
46
47iconsdir = $(datadir)/icons
48icons_DATA = data/icons/eruler.png
49
50EDJE_CC = @edje_cc@
51EDJE_FLAGS_VERBOSE_ =
52EDJE_FLAGS_VERBOSE_0 =
53EDJE_FLAGS_VERBOSE_1 = -v
54EDJE_FLAGS = $(EDJE_FLAGS_VERBOSE_$(V))
55AM_V_EDJ = $(am__v_EDJ_$(V))
56am__v_EDJ_ = $(am__v_EDJ_$(AM_DEFAULT_VERBOSITY))
57am__v_EDJ_0 = @echo " EDJ " $@;
58
59themesdir = $(pkgdatadir)/themes
60themes_DATA = data/themes/default.edj
61themes_sources = data/themes/default.edc
62
63data/themes/default.edj: Makefile data/themes/default.edc
64 @$(MKDIR_P) $(top_builddir)/data/themes
65 $(AM_V_EDJ)$(EDJE_CC) $(EDJE_FLAGS) \
66 $(top_srcdir)/data/themes/default.edc \
67 $(top_builddir)/data/themes/default.edj
68
69EXTRA_DIST = README AUTHORS COPYING autogen.sh \
70$(desktop_DATA) \
71$(icons_DATA) \
72$(themes_sources)
73
74clean-local:
75 rm -f $(themes_DATA)
diff --git a/README b/README
new file mode 100644
index 0000000..d54cca0
--- /dev/null
+++ b/README
@@ -0,0 +1,79 @@
1ERuler - screen rule and measurement tools.
2
3ERuler is a software that allows on-screen virtual rule and
4measurement of areas.
5
6USAGE
7=====
8
9The traditional use is to press your mouse's left-button to start
10measuring, then move your mouse to the end point and release. This
11will give you a box with both points, the origin coordinates as well
12as the region size -- all in pixels.
13
14One can also use the keyboard to do the above flow by using "Space"
15key to mark start and end points, using the mouse or keyboard arrows
16to move the cursor. While using the arrows one can press "Shift" key
17modifier to use 10 pixels instead of a single one in that direction,
18useful for large regions.
19
20Alternatively one can type the coordinates during runtime by using "@"
21shortcut, or using the "Type coordinates" button. This will give you a
22text entry so you can type "x y width height" values (all separated by
23spaces).
24
25Last but not least you can use the command line argument "--ruler" (-r
26for short) to pre-populate the screen. In the case of using multiple
27screens you must specify the origin as absolute position in a global
28scene (if you have two 800x600 screens side by side and want to
29address the horizontal position 10 in right one, use 810 (800 + 10).
30
31It is possible to change the type/style of the measurement box (ruler)
32by using "t" shortcut or the Style selector in the toolbox.
33
34One can create multiple measurements by using "c" shortcut or the
35"Create Ruler" button in the toolbox. The operations will then all be
36on the newly created ruler. The distance between all rulers are
37displayed in semi-transparent colors and once mouse-over they become
38bolder. If those distance hints are distracting you, use "d" ("Show
39distances") to toggle its visibility.
40
41
42NOTE ABOUT ZOOM
43---------------
44
45There is no way in X11 to zoom into a screen region, particularly if
46we're not the compositor. To provide the zoom capability we take a
47screenshot at the beginning and use this copy. However once the screen
48is updated, the copy becomes out of sync and one must toggle zoom to
49refresh it. You'll see that ERuler will hide itself for a moment then
50restore automatically, this is an implementation annoyance we can't
51get rid anytime soon :-(
52
53
54KEYBOARD SHORTCUTS
55------------------
56
57 * Escape: quit;
58 * F2: toggle ERuler visibility;
59 * p: print size to stdout;
60 * c: create new ruler;
61 * Control-c: clear current zone rulers;
62 * g: toggle display of guide lines;
63 * d: toggle display of distances between boxes;
64 * t: toggle ruler type (dark, light, filled...);
65 * z: toggle zoom;
66 * x: toggle display of colors in hexadecimal;
67 * @: open command box to type ruler placement;
68 * Space: start or stop measure using keyboard;
69 * Left: move ruler start point to the left (Shift to use 10px step);
70 * Control-Left: move ruler end point to the left (Shift to use 10px
71 step);
72 * Right: move ruler start point to the right (Shift to use 10px
73 step);
74 * Control-Right: move ruler end point to the right (Shift to use 10px
75 step);
76 * Up: move ruler start point up (Shift to use 10px step);
77 * Control-Up: move ruler end point up (Shift to use 10px step);
78 * Down: move ruler start point down (Shift to use 10px step);
79 * Control-Down: move ruler end point down (Shift to use 10px step).
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..31ccda0
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,16 @@
1#!/bin/sh
2
3rm -rf autom4te.cache
4rm -f aclocal.m4 ltmain.sh
5
6touch README
7
8echo "Running aclocal..." ; aclocal -I m4 $ACLOCAL_FLAGS || exit 1
9echo "Running autoheader..." ; autoheader || exit 1
10echo "Running autoconf..." ; autoconf || exit 1
11echo "Running libtoolize..." ; (libtoolize --copy --automake || glibtoolize --automake) || exit 1
12echo "Running automake..." ; automake --add-missing --copy --gnu || exit 1
13
14if [ -z "$NOCONFIGURE" ]; then
15 ./configure "$@"
16fi
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..b4d8ebb
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,91 @@
1dnl Process this file with autoconf to produce a configure script.
2
3AC_INIT([eruler], [0.1.0], [enlightenment-devel@lists.sourceforge.net])
4AC_PREREQ([2.60])
5AC_CONFIG_SRCDIR([configure.ac])
6AC_CONFIG_MACRO_DIR([m4])
7
8AC_CONFIG_HEADERS([config.h])
9
10AM_INIT_AUTOMAKE([1.6 dist-bzip2 foreign subdir-objects])
11m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
12
13AC_USE_SYSTEM_EXTENSIONS
14AC_PROG_CC
15AM_PROG_CC_C_O
16AC_C___ATTRIBUTE__
17
18efl_version="1.7.0"
19AC_SUBST(efl_version)
20
21requirements="\
22 elementary >= ${efl_version} \
23 eina >= ${efl_version} \
24 evas >= ${efl_version} \
25 ecore >= ${efl_version} \
26 ecore-file >= ${efl_version} \
27 edje >= ${efl_version} \
28 "
29
30want_ecore_x="yes"
31AC_ARG_ENABLE([ecore-x],
32 [AC_HELP_STRING([--disable-ecore-x], [disable ecore-x support. @<:@default=enabled@:>@])],
33 [want_ecore_x=$enableval], [])
34if test "$want_ecore_x" != "no"; then
35 requirements="${requirements} ecore-x >= ${efl_version}"
36fi
37
38PKG_CHECK_MODULES([ERULER], [${requirements}])
39
40if test "$want_ecore_x" != "no"; then
41 AC_DEFINE([HAVE_ECORE_X], [1], [Should use Ecore_X])
42fi
43AM_CONDITIONAL([HAVE_ECORE_X], [test "$want_ecore_x" != "no"])
44
45EFL_WITH_BIN([edje], [edje-cc], [edje_cc])
46
47with_max_log_level=""
48AC_ARG_WITH(maximum-log-level,
49 [AC_HELP_STRING([--with-maximum-log-level=NUMBER],
50 [limit eruler log level to the given number, any call to EINA_LOG() with values greater than this will be compiled out, ignoring runtime settings, but saving function calls.])],
51 [
52 if test "x${withval}" != "xno"; then
53 if echo "${withval}" | grep -E '^[[0-9]]+$' >/dev/null 2>/dev/null; then
54 AC_MSG_NOTICE([ignoring any EINA_LOG() with level greater than ${withval}])
55 with_max_log_level="${withval}"
56 else
57 AC_MSG_ERROR([--with-maximum-log-level takes a decimal number, got "${withval}" instead.])
58 fi
59 fi
60 ], [:])
61
62if test -n "${with_max_log_level}"; then
63 AC_DEFINE_UNQUOTED(EINA_LOG_LEVEL_MAXIMUM, ${with_max_log_level}, [if set, logging is limited to this amount.])
64fi
65
66AC_CONFIG_FILES([
67Makefile
68])
69
70AC_OUTPUT
71
72#####################################################################
73## Info
74
75echo
76echo
77echo
78echo "------------------------------------------------------------------------"
79echo "$PACKAGE $VERSION"
80echo "------------------------------------------------------------------------"
81echo
82echo "Compilation................: make (or gmake)"
83echo " CPPFLAGS.................: $CPPFLAGS"
84echo " CFLAGS...................: $CFLAGS"
85echo " LDFLAGS..................: $LDFLAGS"
86echo
87echo "Installation...............: make install (as root if needed, with 'su' or 'sudo')"
88echo " prefix...................: $prefix"
89echo
90echo "Platforms:"
91echo " X11......................: ${want_ecore_x}"
diff --git a/data/desktop/eruler.desktop b/data/desktop/eruler.desktop
new file mode 100644
index 0000000..ee8fdf5
--- /dev/null
+++ b/data/desktop/eruler.desktop
@@ -0,0 +1,10 @@
1[Desktop Entry]
2Encoding=UTF-8
3Type=Application
4Name=ERuler
5GenericName=Screen Ruler
6Comment=On-Screen Rule and Measurement
7Exec=eruler
8Icon=eruler
9Categories=Graphics
10StartupWMClass=eruler
diff --git a/data/icons/eruler.png b/data/icons/eruler.png
new file mode 100644
index 0000000..55d6c7f
--- /dev/null
+++ b/data/icons/eruler.png
Binary files differ
diff --git a/data/themes/default.edc b/data/themes/default.edc
new file mode 100644
index 0000000..3e86b82
--- /dev/null
+++ b/data/themes/default.edc
@@ -0,0 +1,1668 @@
1collections {
2
3 styles {
4 style { name: "hint_style";
5 base: "font=Sans font_size=12 align=center color=#dcdcdc style=shadow,bottom shadow_color=#00000080 wrap=word";
6 tag: "hilight" "+ font=Sans:style=Bold style=glow color=#3399ffff glow_color=#3399ff18 align=center glow2_color=#3399ff12";
7 tag: "title" "+ font_size=16 font=Sans:style=Bold";
8 tag: "/title" "- \n \n";
9 tag: "br" "\n";
10 }
11 }
12
13 group {
14 name: "eruler/display_pos";
15
16 parts {
17 part {
18 name: "bg";
19 type: RECT;
20 mouse_events: 0;
21 description {
22 state: "default" 0.0;
23 color: 0 0 0 200;
24 }
25 }
26
27 part {
28 name: "text";
29 type: TEXT;
30 effect: SHADOW;
31 mouse_events: 0;
32 description {
33 state: "default" 0.0;
34 color: 220 220 220 255;
35 color2: 32 32 32 128;
36 rel1.offset: 5 5;
37 rel2.offset: -6 -6;
38 text {
39 font: "Sans";
40 size: 10;
41 min: 1 1;
42 }
43 }
44 }
45
46 }
47 }
48
49 group {
50 name: "eruler/zoom_viewfinder";
51
52 data {
53 item: "ideal_size" "256 256";
54 item: "factor" "10";
55 }
56
57 parts {
58 part {
59 name: "content";
60 type: SWALLOW;
61 mouse_events: 0;
62 description {
63 state: "default" 0.0;
64 }
65 }
66
67 part {
68 name: "top";
69 type: RECT;
70 mouse_events: 0;
71 description {
72 state: "default" 0.0;
73 color: 0 0 0 255;
74 rel2 {
75 relative: 1.0 0.0;
76 offset: -1 0;
77 }
78 }
79 }
80
81 part {
82 name: "bottom";
83 type: RECT;
84 mouse_events: 0;
85 description {
86 state: "default" 0.0;
87 color: 0 0 0 255;
88 rel1 {
89 relative: 0.0 1.0;
90 offset: 0 -1;
91 }
92 }
93 }
94
95 part {
96 name: "left";
97 type: RECT;
98 mouse_events: 0;
99 description {
100 state: "default" 0.0;
101 color: 0 0 0 255;
102 rel1 {
103 relative: 0.0 0.0;
104 offset: 0 1;
105 }
106 rel2 {
107 relative: 0.0 1.0;
108 offset: 0 -2;
109 }
110 }
111 }
112
113 part {
114 name: "right";
115 type: RECT;
116 mouse_events: 0;
117 description {
118 state: "default" 0.0;
119 color: 0 0 0 255;
120 rel1 {
121 relative: 1.0 0.0;
122 offset: -1 1;
123 }
124 rel2 {
125 relative: 1.0 1.0;
126 offset: -1 -2;
127 }
128 }
129 }
130
131 part {
132 name: "guide_h0";
133 type: RECT;
134 mouse_events: 0;
135 description {
136 state: "default" 0.0;
137 color: 255 0 0 255;
138 rel1 {
139 relative: 0.0 0.5;
140 offset: 1 -5;
141 }
142 rel2 {
143 relative: 0.5 0.5;
144 offset: -5 -5;
145 }
146 }
147 }
148
149 part {
150 name: "guide_h1";
151 type: RECT;
152 mouse_events: 0;
153 description {
154 state: "default" 0.0;
155 color: 255 0 0 255;
156 rel1 {
157 relative: 0.0 0.5;
158 offset: 1 4;
159 }
160 rel2 {
161 relative: 0.5 0.5;
162 offset: -5 4;
163 }
164 }
165 }
166
167 part {
168 name: "guide_h2";
169 type: RECT;
170 mouse_events: 0;
171 description {
172 state: "default" 0.0;
173 color: 255 0 0 255;
174 rel1 {
175 relative: 0.5 0.5;
176 offset: 4 -5;
177 }
178 rel2 {
179 relative: 1.0 0.5;
180 offset: -2 -5;
181 }
182 }
183 }
184
185 part {
186 name: "guide_h3";
187 type: RECT;
188 mouse_events: 0;
189 description {
190 state: "default" 0.0;
191 color: 255 0 0 255;
192 rel1 {
193 relative: 0.5 0.5;
194 offset: 4 4;
195 }
196 rel2 {
197 relative: 1.0 0.5;
198 offset: -2 4;
199 }
200 }
201 }
202
203 part {
204 name: "guide_v0";
205 type: RECT;
206 mouse_events: 0;
207 description {
208 state: "default" 0.0;
209 color: 255 0 0 255;
210 rel1 {
211 relative: 0.5 0.0;
212 offset: -5 1;
213 }
214 rel2 {
215 relative: 0.5 0.5;
216 offset: -5 -5;
217 }
218 }
219 }
220
221 part {
222 name: "guide_v1";
223 type: RECT;
224 mouse_events: 0;
225 description {
226 state: "default" 0.0;
227 color: 255 0 0 255;
228 rel1 {
229 relative: 0.5 0.0;
230 offset: 4 1;
231 }
232 rel2 {
233 relative: 0.5 0.5;
234 offset: 4 -5;
235 }
236 }
237 }
238
239 part {
240 name: "guide_v2";
241 type: RECT;
242 mouse_events: 0;
243 description {
244 state: "default" 0.0;
245 color: 255 0 0 255;
246 rel1 {
247 relative: 0.5 0.5;
248 offset: -5 4;
249 }
250 rel2 {
251 relative: 0.5 1.0;
252 offset: -5 -2;
253 }
254 }
255 }
256
257 part {
258 name: "guide_v3";
259 type: RECT;
260 mouse_events: 0;
261 description {
262 state: "default" 0.0;
263 color: 255 0 0 255;
264 rel1 {
265 relative: 0.5 0.5;
266 offset: 4 4;
267 }
268 rel2 {
269 relative: 0.5 1.0;
270 offset: 4 -2;
271 }
272 }
273 }
274
275 part {
276 name: "color_bg";
277 type: RECT;
278 mouse_events: 0;
279 description {
280 state: "default" 0.0;
281 color: 32 32 32 200;
282 rel1 {
283 to: "color";
284 offset: -1 -1;
285 }
286 }
287 }
288
289 part {
290 name: "color";
291 type: TEXT;
292 effect: SHADOW;
293 mouse_events: 0;
294 description {
295 state: "default" 0.0;
296 align: 1.0 1.0;
297 color: 220 220 220 255;
298 color2: 32 32 32 128;
299 rel1 {
300 relative: 1.0 1.0;
301 offset: -5 -2;
302 }
303 rel2 {
304 relative: 1.0 1.0;
305 offset: -5 -2;
306 }
307 text {
308 font: "Sans";
309 size: 10;
310 text: "#ffffff";
311 min: 1 1;
312 }
313 }
314 }
315 }
316 }
317
318 group {
319 name: "eruler/hint";
320
321 parts {
322 part {
323 name: "clipper";
324 type: RECT;
325 mouse_events: 0;
326 description {
327 state: "default" 0.0;
328 color: 255 255 255 255;
329 }
330 description {
331 state: "hidden" 0.0;
332 color: 255 255 255 0;
333 visible: 0;
334 }
335 }
336
337 part {
338 name: "top";
339 type: RECT;
340 mouse_events: 0;
341 clip_to: "clipper";
342 description {
343 state: "default" 0.0;
344 color: 0 0 0 96;
345 rel2 {
346 relative: 1.0 0.0;
347 offset: -1 128;
348 }
349 }
350 }
351
352 part {
353 name: "hint";
354 type: TEXTBLOCK;
355 mouse_events: 0;
356 clip_to: "clipper";
357 description {
358 state: "default" 0.0;
359 rel1.to: "top";
360 rel2.to: "top";
361 text.style: "hint_style";
362 }
363 }
364
365 part {
366 name: "eventarea";
367 type: RECT;
368 mouse_events: 1;
369 repeat_events: 1;
370 description {
371 state: "default" 0.0;
372 color: 0 0 0 0;
373 rel1.to: "top";
374 rel2.to: "top";
375 }
376 }
377
378 programs {
379 program {
380 signal: "mouse,in";
381 source: "eventarea";
382 action: STATE_SET "hidden" 0.0;
383 target: "clipper";
384 transition: ACCELERATE 0.3 CURRENT;
385 }
386 program {
387 signal: "mouse,out";
388 source: "eventarea";
389 action: STATE_SET "default" 0.0;
390 target: "clipper";
391 transition: DECELERATE 0.3 CURRENT;
392 }
393 }
394 }
395 }
396
397 group {
398 name: "eruler/distance_horizontal";
399
400 parts {
401 part {
402 name: "clipper";
403 type: RECT;
404 mouse_events: 0;
405 description {
406 state: "default" 0.0;
407 color: 255 255 255 32;
408 }
409 description {
410 state: "over" 0.0;
411 color: 255 255 255 255;
412 }
413 }
414
415 part {
416 name: "start";
417 type: RECT;
418 mouse_events: 0;
419 clip_to: "clipper";
420 description {
421 state: "default" 0.0;
422 color: 0 255 255 255;
423 rel1 {
424 relative: 0.0 0.0;
425 offset: 0 0;
426 }
427 rel2 {
428 relative: 0.0 1.0;
429 offset: 1 -1;
430 }
431 }
432 }
433
434 part {
435 name: "end";
436 type: RECT;
437 mouse_events: 0;
438 clip_to: "clipper";
439 description {
440 state: "default" 0.0;
441 color: 0 255 255 255;
442 rel1 {
443 relative: 1.0 0.0;
444 offset: -2 0;
445 }
446 rel2 {
447 relative: 1.0 1.0;
448 offset: -1 -1;
449 }
450 }
451 }
452
453 part {
454 name: "link";
455 type: RECT;
456 mouse_events: 0;
457 clip_to: "clipper";
458 description {
459 state: "default" 0.0;
460 color: 0 255 255 255;
461 rel1 {
462 relative: 0.0 0.5;
463 offset: 1 0;
464 }
465 rel2 {
466 relative: 1.0 0.5;
467 offset: -2 0;
468 }
469 }
470 }
471
472 part {
473 name: "display";
474 type: TEXT;
475 effect: SHADOW;
476 mouse_events: 0;
477 description {
478 state: "default" 0.0;
479 color: 0 255 255 255;
480 color2: 32 32 32 128;
481 align: 0.5 1.0;
482 visible: 0;
483 rel1 {
484 relative: 0.0 0.5;
485 offset: 3 -2;
486 }
487 rel2 {
488 relative: 1.0 0.5;
489 offset: -4 -2;
490 }
491 text {
492 font: "Sans";
493 size: 10;
494 min: 1 1;
495 fit: 1 0;
496 size_range: 8 12;
497 }
498 }
499 description {
500 state: "over" 0.0;
501 inherit: "default" 0.0;
502 visible: 1;
503 }
504 }
505
506 part {
507 name: "eventarea";
508 type: RECT;
509 mouse_events: 1;
510 repeat_events: 1;
511 description {
512 state: "default" 0.0;
513 color: 0 0 0 0;
514 }
515 }
516
517 programs {
518 program {
519 signal: "mouse,in";
520 source: "eventarea";
521 action: STATE_SET "over" 0.0;
522 transition: LINEAR 0.2;
523 target: "clipper";
524 target: "display";
525 }
526 program {
527 signal: "mouse,out";
528 source: "eventarea";
529 action: STATE_SET "default" 0.0;
530 transition: LINEAR 0.2;
531 target: "clipper";
532 target: "display";
533 }
534 }
535 }
536 }
537
538 group {
539 name: "eruler/distance_vertical";
540
541 parts {
542 part {
543 name: "clipper";
544 type: RECT;
545 mouse_events: 0;
546 description {
547 state: "default" 0.0;
548 color: 255 255 255 32;
549 }
550 description {
551 state: "over" 0.0;
552 color: 255 255 255 255;
553 }
554 }
555
556 part {
557 name: "start";
558 type: RECT;
559 mouse_events: 0;
560 clip_to: "clipper";
561 description {
562 state: "default" 0.0;
563 color: 255 255 0 255;
564 rel1 {
565 relative: 0.0 0.0;
566 offset: 0 0;
567 }
568 rel2 {
569 relative: 1.0 0.0;
570 offset: -1 0;
571 }
572 }
573 }
574
575 part {
576 name: "end";
577 type: RECT;
578 mouse_events: 0;
579 clip_to: "clipper";
580 description {
581 state: "default" 0.0;
582 color: 255 255 0 255;
583 rel1 {
584 relative: 0.0 1.0;
585 offset: 0 -1;
586 }
587 rel2 {
588 relative: 1.0 1.0;
589 offset: -1 -1;
590 }
591 }
592 }
593
594 part {
595 name: "link";
596 type: RECT;
597 mouse_events: 0;
598 clip_to: "clipper";
599 description {
600 state: "default" 0.0;
601 color: 255 255 0 255;
602 rel1 {
603 relative: 0.5 0.0;
604 offset: 0 1;
605 }
606 rel2 {
607 relative: 0.5 1.0;
608 offset: 0 -2;
609 }
610 }
611 }
612
613 part {
614 name: "display";
615 type: TEXT;
616 effect: SHADOW;
617 mouse_events: 0;
618 description {
619 state: "default" 0.0;
620 color: 255 255 0 255;
621 color2: 32 32 32 128;
622 align: 1.0 0.5;
623 visible: 0;
624 rel1 {
625 relative: 0.5 0.0;
626 offset: -2 3;
627 }
628 rel2 {
629 relative: 0.5 1.0;
630 offset: -2 -4;
631 }
632 text {
633 font: "Sans";
634 size: 10;
635 min: 1 1;
636 fit: 0 1;
637 size_range: 8 12;
638 }
639 }
640 description {
641 state: "over" 0.0;
642 inherit: "default" 0.0;
643 visible: 1;
644 }
645 }
646
647 part {
648 name: "eventarea";
649 type: RECT;
650 mouse_events: 1;
651 repeat_events: 1;
652 description {
653 state: "default" 0.0;
654 color: 0 0 0 0;
655 }
656 }
657
658 programs {
659 program {
660 signal: "mouse,in";
661 source: "eventarea";
662 action: STATE_SET "over" 0.0;
663 transition: LINEAR 0.2;
664 target: "clipper";
665 target: "display";
666 }
667 program {
668 signal: "mouse,out";
669 source: "eventarea";
670 action: STATE_SET "default" 0.0;
671 transition: LINEAR 0.2;
672 target: "clipper";
673 target: "display";
674 }
675 }
676 }
677 }
678
679 group {
680 name: "eruler/rule/default";
681
682 parts {
683 part {
684 name: "fill";
685 type: RECT;
686 mouse_events: 0;
687 description {
688 state: "default" 0.0;
689 color: 0 0 0 0;
690 rel1 {
691 relative: 0.0 0.0;
692 offset: 1 1;
693 }
694 rel2 {
695 relative: 1.0 1.0;
696 offset: -2 -2;
697 }
698 }
699 }
700
701 part {
702 name: "hbar1";
703 type: RECT;
704 mouse_events: 0;
705 description {
706 state: "default" 0.0;
707 color: 32 32 32 128;
708 rel2 {
709 relative: 1.0 0.0;
710 offset: 0 0;
711 }
712 }
713 description {
714 state: "inverted" 0.0;
715 inherit: "default" 0.0;
716 rel1 {
717 relative: 0.0 1.0;
718 offset: 0 -1;
719 }
720 rel2 {
721 relative: 1.0 1.0;
722 offset: -1 -1;
723 }
724 }
725 }
726
727 part {
728 name: "hbar2";
729 type: RECT;
730 mouse_events: 0;
731 description {
732 state: "default" 0.0;
733 color: 220 220 220 128;
734 rel1 {
735 relative: 0.0 1.0;
736 offset: 0 -1;
737 }
738 rel2 {
739 relative: 1.0 1.0;
740 offset: -1 -1;
741 }
742 }
743 description {
744 state: "inverted" 0.0;
745 inherit: "default" 0.0;
746 rel1 {
747 relative: 0.0 0.0;
748 offset: 0 0;
749 }
750 rel2 {
751 relative: 1.0 0.0;
752 offset: -1 0;
753 }
754 }
755 }
756
757 part {
758 name: "vbar1";
759 type: RECT;
760 mouse_events: 0;
761 description {
762 state: "default" 0.0;
763 color: 32 32 32 128;
764 rel1.offset: 0 0;
765 rel2 {
766 relative: 0.0 1.0;
767 offset: 0 -1;
768 }
769 }
770 description {
771 state: "inverted" 0.0;
772 inherit: "default" 0.0;
773 rel1 {
774 relative: 1.0 0.0;
775 offset: -1 0;
776 }
777 rel2 {
778 relative: 1.0 1.0;
779 offset: -1 -1;
780 }
781 }
782 }
783
784 part {
785 name: "vbar2";
786 type: RECT;
787 mouse_events: 0;
788 description {
789 state: "default" 0.0;
790 color: 220 220 220 128;
791 rel1 {
792 relative: 1.0 0.0;
793 offset: -1 0;
794 }
795 rel2 {
796 relative: 1.0 1.0;
797 offset: -1 -1;
798 }
799 }
800 description {
801 state: "inverted" 0.0;
802 inherit: "default" 0.0;
803 rel1 {
804 relative: 0.0 0.0;
805 offset: 0 0;
806 }
807 rel2 {
808 relative: 0.0 1.0;
809 offset: 0 -1;
810 }
811 }
812 }
813
814 part {
815 name: "start";
816 type: RECT;
817 mouse_events: 0;
818 description {
819 state: "default" 0.0;
820 color: 0 255 0 128;
821 rel1.offset: -2 -2;
822 rel2 {
823 relative: 0.0 0.0;
824 offset: 1 1;
825 }
826 }
827 description {
828 state: "inverted-xy" 0.0;
829 inherit: "default" 0.0;
830 rel1.relative: 1.0 1.0;
831 rel2.relative: 1.0 1.0;
832 }
833 description {
834 state: "inverted-x" 0.0;
835 inherit: "default" 0.0;
836 rel1.relative: 1.0 0.0;
837 rel2.relative: 1.0 0.0;
838 }
839 description {
840 state: "inverted-y" 0.0;
841 inherit: "default" 0.0;
842 rel1.relative: 0.0 1.0;
843 rel2.relative: 0.0 1.0;
844 }
845 }
846
847 part {
848 name: "end";
849 type: RECT;
850 mouse_events: 0;
851 description {
852 state: "default" 0.0;
853 color: 0 0 255 128;
854 rel1 {
855 relative: 1.0 1.0;
856 offset: -2 -2;
857 }
858 rel2.offset: 1 1;
859 }
860 description {
861 state: "inverted-xy" 0.0;
862 inherit: "default" 0.0;
863 rel1.relative: 0.0 0.0;
864 rel2.relative: 0.0 0.0;
865 }
866 description {
867 state: "inverted-x" 0.0;
868 inherit: "default" 0.0;
869 rel1.relative: 0.0 1.0;
870 rel2.relative: 0.0 1.0;
871 }
872 description {
873 state: "inverted-y" 0.0;
874 inherit: "default" 0.0;
875 rel1.relative: 1.0 0.0;
876 rel2.relative: 1.0 0.0;
877 }
878 }
879
880 part {
881 name: "display_bg";
882 type: RECT;
883 mouse_events: 0;
884 description {
885 state: "default" 0.0;
886 color: 32 32 32 200;
887 rel1 {
888 to: "display";
889 offset: -1 -1;
890 }
891 rel2 {
892 to: "display";
893 offset: 0 0;
894 }
895 }
896 }
897
898 part {
899 name: "display";
900 type: TEXT;
901 effect: SHADOW;
902 mouse_events: 0;
903 description {
904 state: "default" 0.0;
905 align: 0.5 0.5;
906 color: 220 220 220 255;
907 color2: 32 32 32 128;
908 rel1.relative: 0.5 0.5;
909 rel2.relative: 0.5 0.5;
910 text {
911 font: "Sans:style=Bold";
912 size: 10;
913 min: 1 1;
914 }
915 }
916 }
917 }
918
919 script {
920 public start_x, start_y;
921
922 public message(Msg_Type:type, id, ...) {
923 if ((type == MSG_INT_SET) && (id == 0)) {
924 new sx, sy;
925
926 sx = getarg(2);
927 sy = getarg(3);
928
929 set_int(start_x, sx);
930 set_int(start_y, sy);
931 } else if ((type == MSG_INT_SET) && (id == 1)) {
932 new dx, dy, sx, sy;
933 new buf[64];
934
935 dx = getarg(2);
936 dy = getarg(3);
937
938 sx = get_int(start_x);
939 sy = get_int(start_y);
940
941 snprintf(buf, sizeof(buf), "%dx%d @ %d,%d", dx, dy, sx, sy);
942 set_text(PART:"display", buf);
943
944 if (dx < 0) {
945 set_state(PART:"vbar1", "inverted", 0.0);
946 set_state(PART:"vbar2", "inverted", 0.0);
947 } else {
948 set_state(PART:"vbar1", "default", 0.0);
949 set_state(PART:"vbar2", "default", 0.0);
950 }
951
952 if (dy < 0) {
953 set_state(PART:"hbar1", "inverted", 0.0);
954 set_state(PART:"hbar2", "inverted", 0.0);
955 } else {
956 set_state(PART:"hbar1", "default", 0.0);
957 set_state(PART:"hbar2", "default", 0.0);
958 }
959
960 if (dx < 0 && dy < 0) {
961 set_state(PART:"start", "inverted-xy", 0.0);
962 set_state(PART:"end", "inverted-xy", 0.0);
963 } else if (dx < 0) {
964 set_state(PART:"start", "inverted-x", 0.0);
965 set_state(PART:"end", "inverted-x", 0.0);
966 } else if (dy < 0) {
967 set_state(PART:"start", "inverted-y", 0.0);
968 set_state(PART:"end", "inverted-y", 0.0);
969 } else {
970 set_state(PART:"start", "default", 0.0);
971 set_state(PART:"end", "default", 0.0);
972 }
973 }
974 }
975 }
976 }
977
978 group {
979 name: "eruler/rule/light";
980 inherit: "eruler/rule/default";
981
982 parts {
983 part { name: "vbar1";
984
985 description { state: "default" 0.0; color: 220 220 220 128; }
986 description { state: "inverted" 0.0; color: 220 220 220 128; }
987 }
988 part { name: "vbar2";
989 description { state: "default" 0.0; color: 220 220 220 128; }
990 description { state: "inverted" 0.0; color: 220 220 220 128; }
991 }
992 part { name: "hbar1";
993 description { state: "default" 0.0; color: 220 220 220 128; }
994 description { state: "inverted" 0.0; color: 220 220 220 128; }
995 }
996 part { name: "hbar2";
997 description { state: "default" 0.0; color: 220 220 220 128; }
998 description { state: "inverted" 0.0; color: 220 220 220 128; }
999 }
1000 part { name: "start";
1001 description { state: "default" 0.0; color: 220 220 220 128; }
1002 description { state: "inverted-x" 0.0; color: 220 220 220 128; }
1003 description { state: "inverted-y" 0.0; color: 220 220 220 128; }
1004 description { state: "inverted-xy" 0.0; color: 220 220 220 128; }
1005 }
1006 part { name: "end";
1007 description { state: "default" 0.0; color: 220 220 220 128; }
1008 description { state: "inverted-x" 0.0; color: 220 220 220 128; }
1009 description { state: "inverted-y" 0.0; color: 220 220 220 128; }
1010 description { state: "inverted-xy" 0.0; color: 220 220 220 128; }
1011 }
1012
1013 part {
1014 name: "display_bg"; description { state: "default" 0.0;
1015 color: 220 220 220 200;
1016 }
1017 }
1018 part {
1019 name: "display";
1020 effect: NONE;
1021 description { state: "default" 0.0;
1022 color: 32 32 32 255;
1023 color2: 220 220 220 128;
1024 }
1025 }
1026 }
1027
1028 script {
1029 public start_x, start_y;
1030
1031 public message(Msg_Type:type, id, ...) {
1032 if ((type == MSG_INT_SET) && (id == 0)) {
1033 new sx, sy;
1034
1035 sx = getarg(2);
1036 sy = getarg(3);
1037
1038 set_int(start_x, sx);
1039 set_int(start_y, sy);
1040 } else if ((type == MSG_INT_SET) && (id == 1)) {
1041 new dx, dy, sx, sy;
1042 new buf[64];
1043
1044 dx = getarg(2);
1045 dy = getarg(3);
1046
1047 sx = get_int(start_x);
1048 sy = get_int(start_y);
1049
1050 snprintf(buf, sizeof(buf), "%dx%d @ %d,%d", dx, dy, sx, sy);
1051 set_text(PART:"display", buf);
1052
1053 if (dx < 0) {
1054 set_state(PART:"vbar1", "inverted", 0.0);
1055 set_state(PART:"vbar2", "inverted", 0.0);
1056 } else {
1057 set_state(PART:"vbar1", "default", 0.0);
1058 set_state(PART:"vbar2", "default", 0.0);
1059 }
1060
1061 if (dy < 0) {
1062 set_state(PART:"hbar1", "inverted", 0.0);
1063 set_state(PART:"hbar2", "inverted", 0.0);
1064 } else {
1065 set_state(PART:"hbar1", "default", 0.0);
1066 set_state(PART:"hbar2", "default", 0.0);
1067 }
1068
1069 if (dx < 0 && dy < 0) {
1070 set_state(PART:"start", "inverted-xy", 0.0);
1071 set_state(PART:"end", "inverted-xy", 0.0);
1072 } else if (dx < 0) {
1073 set_state(PART:"start", "inverted-x", 0.0);
1074 set_state(PART:"end", "inverted-x", 0.0);
1075 } else if (dy < 0) {
1076 set_state(PART:"start", "inverted-y", 0.0);
1077 set_state(PART:"end", "inverted-y", 0.0);
1078 } else {
1079 set_state(PART:"start", "default", 0.0);
1080 set_state(PART:"end", "default", 0.0);
1081 }
1082 }
1083 }
1084 }
1085 }
1086
1087 group {
1088 name: "eruler/rule/dark";
1089 inherit: "eruler/rule/default";
1090
1091 parts {
1092 part { name: "vbar1";
1093
1094 description { state: "default" 0.0; color: 32 32 32 128; }
1095 description { state: "inverted" 0.0; color: 32 32 32 128; }
1096 }
1097 part { name: "vbar2";
1098 description { state: "default" 0.0; color: 32 32 32 128; }
1099 description { state: "inverted" 0.0; color: 32 32 32 128; }
1100 }
1101 part { name: "hbar1";
1102 description { state: "default" 0.0; color: 32 32 32 128; }
1103 description { state: "inverted" 0.0; color: 32 32 32 128; }
1104 }
1105 part { name: "hbar2";
1106 description { state: "default" 0.0; color: 32 32 32 128; }
1107 description { state: "inverted" 0.0; color: 32 32 32 128; }
1108 }
1109 part { name: "start";
1110 description { state: "default" 0.0; color: 32 32 32 128; }
1111 description { state: "inverted-x" 0.0; color: 32 32 32 128; }
1112 description { state: "inverted-y" 0.0; color: 32 32 32 128; }
1113 description { state: "inverted-xy" 0.0; color: 32 32 32 128; }
1114 }
1115 part { name: "end";
1116 description { state: "default" 0.0; color: 32 32 32 128; }
1117 description { state: "inverted-x" 0.0; color: 32 32 32 128; }
1118 description { state: "inverted-y" 0.0; color: 32 32 32 128; }
1119 description { state: "inverted-xy" 0.0; color: 32 32 32 128; }
1120 }
1121 }
1122
1123 script {
1124 public start_x, start_y;
1125
1126 public message(Msg_Type:type, id, ...) {
1127 if ((type == MSG_INT_SET) && (id == 0)) {
1128 new sx, sy;
1129
1130 sx = getarg(2);
1131 sy = getarg(3);
1132
1133 set_int(start_x, sx);
1134 set_int(start_y, sy);
1135 } else if ((type == MSG_INT_SET) && (id == 1)) {
1136 new dx, dy, sx, sy;
1137 new buf[64];
1138
1139 dx = getarg(2);
1140 dy = getarg(3);
1141
1142 sx = get_int(start_x);
1143 sy = get_int(start_y);
1144
1145 snprintf(buf, sizeof(buf), "%dx%d @ %d,%d", dx, dy, sx, sy);
1146 set_text(PART:"display", buf);
1147
1148 if (dx < 0) {
1149 set_state(PART:"vbar1", "inverted", 0.0);
1150 set_state(PART:"vbar2", "inverted", 0.0);
1151 } else {
1152 set_state(PART:"vbar1", "default", 0.0);
1153 set_state(PART:"vbar2", "default", 0.0);
1154 }
1155
1156 if (dy < 0) {
1157 set_state(PART:"hbar1", "inverted", 0.0);
1158 set_state(PART:"hbar2", "inverted", 0.0);
1159 } else {
1160 set_state(PART:"hbar1", "default", 0.0);
1161 set_state(PART:"hbar2", "default", 0.0);
1162 }
1163
1164 if (dx < 0 && dy < 0) {
1165 set_state(PART:"start", "inverted-xy", 0.0);
1166 set_state(PART:"end", "inverted-xy", 0.0);
1167 } else if (dx < 0) {
1168 set_state(PART:"start", "inverted-x", 0.0);
1169 set_state(PART:"end", "inverted-x", 0.0);
1170 } else if (dy < 0) {
1171 set_state(PART:"start", "inverted-y", 0.0);
1172 set_state(PART:"end", "inverted-y", 0.0);
1173 } else {
1174 set_state(PART:"start", "default", 0.0);
1175 set_state(PART:"end", "default", 0.0);
1176 }
1177 }
1178 }
1179 }
1180 }
1181
1182 group {
1183 name: "eruler/rule/light-filled";
1184 inherit: "eruler/rule/light";
1185
1186 parts {
1187 part {
1188 name: "fill"; description { state: "default" 0.0;
1189 color: 220 220 220 96;
1190 }
1191 }
1192 part {
1193 name: "display_bg"; description { state: "default" 0.0;
1194 color: 0 0 0 0;
1195 }
1196 }
1197 part {
1198 name: "display";
1199 effect: NONE;
1200 description { state: "default" 0.0;
1201 color: 32 32 32 255;
1202 color2: 220 220 220 128;
1203 }
1204 }
1205 }
1206
1207 script {
1208 public start_x, start_y;
1209
1210 public message(Msg_Type:type, id, ...) {
1211 if ((type == MSG_INT_SET) && (id == 0)) {
1212 new sx, sy;
1213
1214 sx = getarg(2);
1215 sy = getarg(3);
1216
1217 set_int(start_x, sx);
1218 set_int(start_y, sy);
1219 } else if ((type == MSG_INT_SET) && (id == 1)) {
1220 new dx, dy, sx, sy;
1221 new buf[64];
1222
1223 dx = getarg(2);
1224 dy = getarg(3);
1225
1226 sx = get_int(start_x);
1227 sy = get_int(start_y);
1228
1229 snprintf(buf, sizeof(buf), "%dx%d @ %d,%d", dx, dy, sx, sy);
1230 set_text(PART:"display", buf);
1231
1232 if (dx < 0) {
1233 set_state(PART:"vbar1", "inverted", 0.0);
1234 set_state(PART:"vbar2", "inverted", 0.0);
1235 } else {
1236 set_state(PART:"vbar1", "default", 0.0);
1237 set_state(PART:"vbar2", "default", 0.0);
1238 }
1239
1240 if (dy < 0) {
1241 set_state(PART:"hbar1", "inverted", 0.0);
1242 set_state(PART:"hbar2", "inverted", 0.0);
1243 } else {
1244 set_state(PART:"hbar1", "default", 0.0);
1245 set_state(PART:"hbar2", "default", 0.0);
1246 }
1247
1248 if (dx < 0 && dy < 0) {
1249 set_state(PART:"start", "inverted-xy", 0.0);
1250 set_state(PART:"end", "inverted-xy", 0.0);
1251 } else if (dx < 0) {
1252 set_state(PART:"start", "inverted-x", 0.0);
1253 set_state(PART:"end", "inverted-x", 0.0);
1254 } else if (dy < 0) {
1255 set_state(PART:"start", "inverted-y", 0.0);
1256 set_state(PART:"end", "inverted-y", 0.0);
1257 } else {
1258 set_state(PART:"start", "default", 0.0);
1259 set_state(PART:"end", "default", 0.0);
1260 }
1261 }
1262 }
1263 }
1264 }
1265
1266 group {
1267 name: "eruler/rule/dark-filled";
1268 inherit: "eruler/rule/dark";
1269
1270 parts {
1271 part {
1272 name: "fill"; description { state: "default" 0.0;
1273 color: 32 32 32 96;
1274 }
1275 }
1276 part {
1277 name: "display_bg"; description { state: "default" 0.0;
1278 color: 0 0 0 0;
1279 }
1280 }
1281 }
1282
1283 script {
1284 public start_x, start_y;
1285
1286 public message(Msg_Type:type, id, ...) {
1287 if ((type == MSG_INT_SET) && (id == 0)) {
1288 new sx, sy;
1289
1290 sx = getarg(2);
1291 sy = getarg(3);
1292
1293 set_int(start_x, sx);
1294 set_int(start_y, sy);
1295 } else if ((type == MSG_INT_SET) && (id == 1)) {
1296 new dx, dy, sx, sy;
1297 new buf[64];
1298
1299 dx = getarg(2);
1300 dy = getarg(3);
1301
1302 sx = get_int(start_x);
1303 sy = get_int(start_y);
1304
1305 snprintf(buf, sizeof(buf), "%dx%d @ %d,%d", dx, dy, sx, sy);
1306 set_text(PART:"display", buf);
1307
1308 if (dx < 0) {
1309 set_state(PART:"vbar1", "inverted", 0.0);
1310 set_state(PART:"vbar2", "inverted", 0.0);
1311 } else {
1312 set_state(PART:"vbar1", "default", 0.0);
1313 set_state(PART:"vbar2", "default", 0.0);
1314 }
1315
1316 if (dy < 0) {
1317 set_state(PART:"hbar1", "inverted", 0.0);
1318 set_state(PART:"hbar2", "inverted", 0.0);
1319 } else {
1320 set_state(PART:"hbar1", "default", 0.0);
1321 set_state(PART:"hbar2", "default", 0.0);
1322 }
1323
1324 if (dx < 0 && dy < 0) {
1325 set_state(PART:"start", "inverted-xy", 0.0);
1326 set_state(PART:"end", "inverted-xy", 0.0);
1327 } else if (dx < 0) {
1328 set_state(PART:"start", "inverted-x", 0.0);
1329 set_state(PART:"end", "inverted-x", 0.0);
1330 } else if (dy < 0) {
1331 set_state(PART:"start", "inverted-y", 0.0);
1332 set_state(PART:"end", "inverted-y", 0.0);
1333 } else {
1334 set_state(PART:"start", "default", 0.0);
1335 set_state(PART:"end", "default", 0.0);
1336 }
1337 }
1338 }
1339 }
1340 }
1341
1342 group {
1343 name: "eruler/rule/good";
1344 inherit: "eruler/rule/default";
1345
1346 parts {
1347 part { name: "vbar1";
1348
1349 description { state: "default" 0.0; color: 96 255 96 128; }
1350 description { state: "inverted" 0.0; color: 96 255 96 128; }
1351 }
1352 part { name: "vbar2";
1353 description { state: "default" 0.0; color: 96 255 96 128; }
1354 description { state: "inverted" 0.0; color: 96 255 96 128; }
1355 }
1356 part { name: "hbar1";
1357 description { state: "default" 0.0; color: 96 255 96 128; }
1358 description { state: "inverted" 0.0; color: 96 255 96 128; }
1359 }
1360 part { name: "hbar2";
1361 description { state: "default" 0.0; color: 96 255 96 128; }
1362 description { state: "inverted" 0.0; color: 96 255 96 128; }
1363 }
1364 part { name: "start";
1365 description { state: "default" 0.0; color: 96 255 96 128; }
1366 description { state: "inverted-x" 0.0; color: 96 255 96 128; }
1367 description { state: "inverted-y" 0.0; color: 96 255 96 128; }
1368 description { state: "inverted-xy" 0.0; color: 96 255 96 128; }
1369 }
1370 part { name: "end";
1371 description { state: "default" 0.0; color: 96 255 96 128; }
1372 description { state: "inverted-x" 0.0; color: 96 255 96 128; }
1373 description { state: "inverted-y" 0.0; color: 96 255 96 128; }
1374 description { state: "inverted-xy" 0.0; color: 96 255 96 128; }
1375 }
1376
1377 part {
1378 name: "display_bg"; description { state: "default" 0.0;
1379 color: 96 255 96 128;
1380 }
1381 }
1382
1383 part {
1384 name: "display";
1385 effect: NONE;
1386 description { state: "default" 0.0;
1387 color: 32 32 32 255;
1388 }
1389 }
1390 }
1391
1392 script {
1393 public start_x, start_y;
1394
1395 public message(Msg_Type:type, id, ...) {
1396 if ((type == MSG_INT_SET) && (id == 0)) {
1397 new sx, sy;
1398
1399 sx = getarg(2);
1400 sy = getarg(3);
1401
1402 set_int(start_x, sx);
1403 set_int(start_y, sy);
1404 } else if ((type == MSG_INT_SET) && (id == 1)) {
1405 new dx, dy, sx, sy;
1406 new buf[64];
1407
1408 dx = getarg(2);
1409 dy = getarg(3);
1410
1411 sx = get_int(start_x);
1412 sy = get_int(start_y);
1413
1414 snprintf(buf, sizeof(buf), "%dx%d @ %d,%d", dx, dy, sx, sy);
1415 set_text(PART:"display", buf);
1416
1417 if (dx < 0) {
1418 set_state(PART:"vbar1", "inverted", 0.0);
1419 set_state(PART:"vbar2", "inverted", 0.0);
1420 } else {
1421 set_state(PART:"vbar1", "default", 0.0);
1422 set_state(PART:"vbar2", "default", 0.0);
1423 }
1424
1425 if (dy < 0) {
1426 set_state(PART:"hbar1", "inverted", 0.0);
1427 set_state(PART:"hbar2", "inverted", 0.0);
1428 } else {
1429 set_state(PART:"hbar1", "default", 0.0);
1430 set_state(PART:"hbar2", "default", 0.0);
1431 }
1432
1433 if (dx < 0 && dy < 0) {
1434 set_state(PART:"start", "inverted-xy", 0.0);
1435 set_state(PART:"end", "inverted-xy", 0.0);
1436 } else if (dx < 0) {
1437 set_state(PART:"start", "inverted-x", 0.0);
1438 set_state(PART:"end", "inverted-x", 0.0);
1439 } else if (dy < 0) {
1440 set_state(PART:"start", "inverted-y", 0.0);
1441 set_state(PART:"end", "inverted-y", 0.0);
1442 } else {
1443 set_state(PART:"start", "default", 0.0);
1444 set_state(PART:"end", "default", 0.0);
1445 }
1446 }
1447 }
1448 }
1449 }
1450
1451 group {
1452 name: "eruler/rule/warning";
1453 inherit: "eruler/rule/default";
1454
1455 parts {
1456 part { name: "vbar1";
1457
1458 description { state: "default" 0.0; color: 255 255 96 128; }
1459 description { state: "inverted" 0.0; color: 255 255 96 128; }
1460 }
1461 part { name: "vbar2";
1462 description { state: "default" 0.0; color: 255 255 96 128; }
1463 description { state: "inverted" 0.0; color: 255 255 96 128; }
1464 }
1465 part { name: "hbar1";
1466 description { state: "default" 0.0; color: 255 255 96 128; }
1467 description { state: "inverted" 0.0; color: 255 255 96 128; }
1468 }
1469 part { name: "hbar2";
1470 description { state: "default" 0.0; color: 255 255 96 128; }
1471 description { state: "inverted" 0.0; color: 255 255 96 128; }
1472 }
1473 part { name: "start";
1474 description { state: "default" 0.0; color: 255 255 96 128; }
1475 description { state: "inverted-x" 0.0; color: 255 255 96 128; }
1476 description { state: "inverted-y" 0.0; color: 255 255 96 128; }
1477 description { state: "inverted-xy" 0.0; color: 255 255 96 128; }
1478 }
1479 part { name: "end";
1480 description { state: "default" 0.0; color: 255 255 96 128; }
1481 description { state: "inverted-x" 0.0; color: 255 255 96 128; }
1482 description { state: "inverted-y" 0.0; color: 255 255 96 128; }
1483 description { state: "inverted-xy" 0.0; color: 255 255 96 128; }
1484 }
1485
1486 part {
1487 name: "display_bg"; description { state: "default" 0.0;
1488 color: 255 255 96 128;
1489 }
1490 }
1491
1492 part {
1493 name: "display";
1494 effect: NONE;
1495 description { state: "default" 0.0;
1496 color: 32 32 32 255;
1497 }
1498 }
1499 }
1500
1501 script {
1502 public start_x, start_y;
1503
1504 public message(Msg_Type:type, id, ...) {
1505 if ((type == MSG_INT_SET) && (id == 0)) {
1506 new sx, sy;
1507
1508 sx = getarg(2);
1509 sy = getarg(3);
1510
1511 set_int(start_x, sx);
1512 set_int(start_y, sy);
1513 } else if ((type == MSG_INT_SET) && (id == 1)) {
1514 new dx, dy, sx, sy;
1515 new buf[64];
1516
1517 dx = getarg(2);
1518 dy = getarg(3);
1519
1520 sx = get_int(start_x);
1521 sy = get_int(start_y);
1522
1523 snprintf(buf, sizeof(buf), "%dx%d @ %d,%d", dx, dy, sx, sy);
1524 set_text(PART:"display", buf);
1525
1526 if (dx < 0) {
1527 set_state(PART:"vbar1", "inverted", 0.0);
1528 set_state(PART:"vbar2", "inverted", 0.0);
1529 } else {
1530 set_state(PART:"vbar1", "default", 0.0);
1531 set_state(PART:"vbar2", "default", 0.0);
1532 }
1533
1534 if (dy < 0) {
1535 set_state(PART:"hbar1", "inverted", 0.0);
1536 set_state(PART:"hbar2", "inverted", 0.0);
1537 } else {
1538 set_state(PART:"hbar1", "default", 0.0);
1539 set_state(PART:"hbar2", "default", 0.0);
1540 }
1541
1542 if (dx < 0 && dy < 0) {
1543 set_state(PART:"start", "inverted-xy", 0.0);
1544 set_state(PART:"end", "inverted-xy", 0.0);
1545 } else if (dx < 0) {
1546 set_state(PART:"start", "inverted-x", 0.0);
1547 set_state(PART:"end", "inverted-x", 0.0);
1548 } else if (dy < 0) {
1549 set_state(PART:"start", "inverted-y", 0.0);
1550 set_state(PART:"end", "inverted-y", 0.0);
1551 } else {
1552 set_state(PART:"start", "default", 0.0);
1553 set_state(PART:"end", "default", 0.0);
1554 }
1555 }
1556 }
1557 }
1558 }
1559
1560 group {
1561 name: "eruler/rule/bad";
1562 inherit: "eruler/rule/default";
1563
1564 parts {
1565 part { name: "vbar1";
1566
1567 description { state: "default" 0.0; color: 255 96 96 128; }
1568 description { state: "inverted" 0.0; color: 255 96 96 128; }
1569 }
1570 part { name: "vbar2";
1571 description { state: "default" 0.0; color: 255 96 96 128; }
1572 description { state: "inverted" 0.0; color: 255 96 96 128; }
1573 }
1574 part { name: "hbar1";
1575 description { state: "default" 0.0; color: 255 96 96 128; }
1576 description { state: "inverted" 0.0; color: 255 96 96 128; }
1577 }
1578 part { name: "hbar2";
1579 description { state: "default" 0.0; color: 255 96 96 128; }
1580 description { state: "inverted" 0.0; color: 255 96 96 128; }
1581 }
1582 part { name: "start";
1583 description { state: "default" 0.0; color: 255 96 96 128; }
1584 description { state: "inverted-x" 0.0; color: 255 96 96 128; }
1585 description { state: "inverted-y" 0.0; color: 255 96 96 128; }
1586 description { state: "inverted-xy" 0.0; color: 255 96 96 128; }
1587 }
1588 part { name: "end";
1589 description { state: "default" 0.0; color: 255 96 96 128; }
1590 description { state: "inverted-x" 0.0; color: 255 96 96 128; }
1591 description { state: "inverted-y" 0.0; color: 255 96 96 128; }
1592 description { state: "inverted-xy" 0.0; color: 255 96 96 128; }
1593 }
1594
1595 part {
1596 name: "display_bg"; description { state: "default" 0.0;
1597 color: 255 96 96 128;
1598 }
1599 }
1600
1601 part {
1602 name: "display";
1603 effect: NONE;
1604 description { state: "default" 0.0;
1605 color: 32 32 32 255;
1606 }
1607 }
1608 }
1609
1610 script {
1611 public start_x, start_y;
1612
1613 public message(Msg_Type:type, id, ...) {
1614 if ((type == MSG_INT_SET) && (id == 0)) {
1615 new sx, sy;
1616
1617 sx = getarg(2);
1618 sy = getarg(3);
1619
1620 set_int(start_x, sx);
1621 set_int(start_y, sy);
1622 } else if ((type == MSG_INT_SET) && (id == 1)) {
1623 new dx, dy, sx, sy;
1624 new buf[64];
1625
1626 dx = getarg(2);
1627 dy = getarg(3);
1628
1629 sx = get_int(start_x);
1630 sy = get_int(start_y);
1631
1632 snprintf(buf, sizeof(buf), "%dx%d @ %d,%d", dx, dy, sx, sy);
1633 set_text(PART:"display", buf);
1634
1635 if (dx < 0) {
1636 set_state(PART:"vbar1", "inverted", 0.0);
1637 set_state(PART:"vbar2", "inverted", 0.0);
1638 } else {
1639 set_state(PART:"vbar1", "default", 0.0);
1640 set_state(PART:"vbar2", "default", 0.0);
1641 }
1642
1643 if (dy < 0) {
1644 set_state(PART:"hbar1", "inverted", 0.0);
1645 set_state(PART:"hbar2", "inverted", 0.0);
1646 } else {
1647 set_state(PART:"hbar1", "default", 0.0);
1648 set_state(PART:"hbar2", "default", 0.0);
1649 }
1650
1651 if (dx < 0 && dy < 0) {
1652 set_state(PART:"start", "inverted-xy", 0.0);
1653 set_state(PART:"end", "inverted-xy", 0.0);
1654 } else if (dx < 0) {
1655 set_state(PART:"start", "inverted-x", 0.0);
1656 set_state(PART:"end", "inverted-x", 0.0);
1657 } else if (dy < 0) {
1658 set_state(PART:"start", "inverted-y", 0.0);
1659 set_state(PART:"end", "inverted-y", 0.0);
1660 } else {
1661 set_state(PART:"start", "default", 0.0);
1662 set_state(PART:"end", "default", 0.0);
1663 }
1664 }
1665 }
1666 }
1667 }
1668}
diff --git a/m4/ac_attribute.m4 b/m4/ac_attribute.m4
new file mode 100644
index 0000000..23479a9
--- /dev/null
+++ b/m4/ac_attribute.m4
@@ -0,0 +1,47 @@
1dnl Copyright (C) 2004-2008 Kim Woelders
2dnl Copyright (C) 2008 Vincent Torri <vtorri at univ-evry dot fr>
3dnl That code is public domain and can be freely used or copied.
4dnl Originally snatched from somewhere...
5
6dnl Macro for checking if the compiler supports __attribute__
7
8dnl Usage: AC_C___ATTRIBUTE__
9dnl call AC_DEFINE for HAVE___ATTRIBUTE__ and __UNUSED__
10dnl if the compiler supports __attribute__, HAVE___ATTRIBUTE__ is
11dnl defined to 1 and __UNUSED__ is defined to __attribute__((unused))
12dnl otherwise, HAVE___ATTRIBUTE__ is not defined and __UNUSED__ is
13dnl defined to nothing.
14
15AC_DEFUN([AC_C___ATTRIBUTE__],
16[
17
18AC_MSG_CHECKING([for __attribute__])
19
20AC_CACHE_VAL([ac_cv___attribute__],
21 [AC_TRY_COMPILE(
22 [
23#include <stdlib.h>
24
25int func(int x);
26int foo(int x __attribute__ ((unused)))
27{
28 exit(1);
29}
30 ],
31 [],
32 [ac_cv___attribute__="yes"],
33 [ac_cv___attribute__="no"]
34 )])
35
36AC_MSG_RESULT($ac_cv___attribute__)
37
38if test "x${ac_cv___attribute__}" = "xyes" ; then
39 AC_DEFINE([HAVE___ATTRIBUTE__], [1], [Define to 1 if your compiler has __attribute__])
40 AC_DEFINE([__UNUSED__], [__attribute__((unused))], [Macro declaring a function argument to be unused])
41 else
42 AC_DEFINE([__UNUSED__], [], [Macro declaring a function argument to be unused])
43fi
44
45])
46
47dnl End of ac_attribute.m4
diff --git a/m4/efl_binary.m4 b/m4/efl_binary.m4
new file mode 100644
index 0000000..c774688
--- /dev/null
+++ b/m4/efl_binary.m4
@@ -0,0 +1,71 @@
1dnl Copyright (C) 2010 Vincent Torri <vtorri at univ-evry dot fr>
2dnl That code is public domain and can be freely used or copied.
3
4dnl Macro that check if a binary is built or not
5
6dnl Usage: EFL_ENABLE_BIN(binary)
7dnl Call AC_SUBST(BINARY_PRG) (BINARY is the uppercase of binary, - being transformed into _)
8dnl Define have_binary (- is transformed into _)
9dnl Define conditional BUILD_BINARY (BINARY is the uppercase of binary, - being transformed into _)
10
11AC_DEFUN([EFL_ENABLE_BIN],
12[
13
14m4_pushdef([UP], m4_translit([[$1]], [-a-z], [_A-Z]))dnl
15m4_pushdef([DOWN], m4_translit([[$1]], [-A-Z], [_a-z]))dnl
16
17have_[]m4_defn([DOWN])="yes"
18
19dnl configure option
20
21AC_ARG_ENABLE([$1],
22 [AC_HELP_STRING([--disable-$1], [disable building of ]DOWN)],
23 [
24 if test "x${enableval}" = "xyes" ; then
25 have_[]m4_defn([DOWN])="yes"
26 else
27 have_[]m4_defn([DOWN])="no"
28 fi
29 ])
30
31AC_MSG_CHECKING([whether to build ]DOWN[ binary])
32AC_MSG_RESULT([$have_[]m4_defn([DOWN])])
33
34if test "x$have_[]m4_defn([DOWN])" = "xyes"; then
35 UP[]_PRG=DOWN[${EXEEXT}]
36fi
37
38AC_SUBST(UP[]_PRG)
39
40AM_CONDITIONAL(BUILD_[]UP, test "x$have_[]m4_defn([DOWN])" = "xyes")
41
42AS_IF([test "x$have_[]m4_defn([DOWN])" = "xyes"], [$2], [$3])
43
44])
45
46
47dnl Macro that check if a binary is built or not
48
49dnl Usage: EFL_WITH_BIN(package, binary, default_value)
50dnl Call AC_SUBST(_binary) (_binary is the lowercase of binary, - being transformed into _ by default, or the value set by the user)
51
52AC_DEFUN([EFL_WITH_BIN],
53[
54
55m4_pushdef([DOWN], m4_translit([[$2]], [-A-Z], [_a-z]))dnl
56
57dnl configure option
58
59AC_ARG_WITH([$2],
60 [AC_HELP_STRING([--with-$2=PATH], [specify a specific path to ]DOWN[ @<:@default=$3@:>@])],
61 [_efl_with_binary=${withval}],
62 [_efl_with_binary=$(pkg-config --variable=prefix $1)/bin/$3])
63
64DOWN=${_efl_with_binary}
65AC_MSG_NOTICE(DOWN[ set to ${_efl_with_binary}])
66
67with_binary_[]m4_defn([DOWN])=${_efl_with_binary}
68
69AC_SUBST(DOWN)
70
71])
diff --git a/src/bin/main.c b/src/bin/main.c
new file mode 100644
index 0000000..1d88ff8
--- /dev/null
+++ b/src/bin/main.c
@@ -0,0 +1,2663 @@
1#include "private.h"
2
3#include <Ecore_Getopt.h>
4#include <Elementary_Cursor.h>
5#include <Ecore_File.h>
6
7static void
8_group_smart_set_user(Evas_Smart_Class *sc EINA_UNUSED)
9{
10}
11
12EVAS_SMART_SUBCLASS_NEW("Group", _group,
13 Evas_Smart_Class, Evas_Smart_Class,
14 evas_object_smart_clipped_class_get, NULL);
15
16static Evas_Object *
17group_add(Evas *evas)
18{
19 return evas_object_smart_add(evas, _group_smart_class_new());
20}
21
22
23struct _Zone {
24 Evas *evas;
25 Evas_Object *win;
26 Evas_Object *event;
27 Evas_Object *handling;
28 Evas_Object *hint;
29 Evas_Object *guide_h;
30 Evas_Object *guide_v;
31 Evas_Object *display_pos;
32 Evas_Object *cmdbox;
33 struct {
34 Evas_Object *frame;
35 Evas_Object *main_box;
36 Evas_Object *create;
37 Evas_Object *clear;
38 Evas_Object *style;
39 Evas_Object *zoom;
40 Evas_Object *show_guides;
41 Evas_Object *show_distances;
42 Evas_Object *hex_colors;
43 struct {
44 int x, y, dx, dy;
45 Ecore_Animator *anim;
46 } moving;
47 } gui;
48 struct {
49 Evas_Object *frame;
50 Evas_Object *image;
51 struct {
52 int w, h;
53 } ideal_size;
54 int factor;
55 Eina_Bool ready : 1;
56 } zoom;
57 struct {
58 Ecore_Evas *ee;
59 Evas_Object *image; /* lives inside ee */
60 /* the following are inside zone->win */
61 Evas_Object *popup;
62 Evas_Object *save_bt;
63 Evas_Object *cancel_bt;
64 struct {
65 Evas_Object *entry;
66 Evas_Object *button;
67 Evas_Object *popup;
68 Evas_Object *selector;
69 } file;
70 Evas_Object *preview;
71 Ecore_Timer *timer;
72 } screenshot;
73 struct {
74 Evas_Object *rulers;
75 Evas_Object *distances;
76 } group;
77 Eina_List *rulers;
78 Eina_List *distances;
79 Ecore_Animator *tracker;
80 int idx;
81 int x, y, w, h;
82 struct {
83 int x, y;
84 } last_mouse;
85 Eina_Bool last_ruler_used : 1;
86 Eina_Bool keyboard_move : 1;
87};
88
89static Eina_List *zones;
90static const Platform_Funcs *platform_funcs;
91static Eina_Bool show_distances = EINA_TRUE;
92static Eina_Bool show_guides = EINA_TRUE;
93static Eina_Bool hex_colors = EINA_FALSE;
94static Eina_Bool visible = EINA_TRUE;
95static int retval = EXIT_SUCCESS;
96
97int _log_dom = -1;
98
99enum ruler_type {
100 RULER_TYPE_DEFAULT = 0,
101 RULER_TYPE_LIGHT,
102 RULER_TYPE_DARK,
103 RULER_TYPE_LIGHT_FILLED,
104 RULER_TYPE_DARK_FILLED,
105 RULER_TYPE_GOOD,
106 RULER_TYPE_WARNING,
107 RULER_TYPE_BAD,
108 RULER_TYPE_SENTINEL
109};
110
111static enum ruler_type initial_ruler_type = RULER_TYPE_DEFAULT;
112static char theme_file[PATH_MAX];
113
114#define RULER_TYPE_PREFIX "eruler/rule/"
115
116static const char *ruler_type_names_strs[] = {
117 [RULER_TYPE_DEFAULT] = "default",
118 [RULER_TYPE_LIGHT] = "light",
119 [RULER_TYPE_DARK] = "dark",
120 [RULER_TYPE_LIGHT_FILLED] = "light-filled",
121 [RULER_TYPE_DARK_FILLED] = "dark-filled",
122 [RULER_TYPE_GOOD] = "good",
123 [RULER_TYPE_WARNING] = "warning",
124 [RULER_TYPE_BAD] = "bad",
125 [RULER_TYPE_SENTINEL] = NULL,
126};
127#define N_RULER_TYPES (EINA_C_ARRAY_LENGTH(ruler_type_names_strs) - 1)
128
129
130typedef struct _Distance Distance;
131typedef struct _Ruler_Data Ruler_Data;
132
133struct _Distance {
134 Zone *zone;
135 Evas_Object *a, *b;
136 Evas_Object *top, *bottom, *left, *right;
137};
138
139struct _Ruler_Data {
140 Zone *zone;
141 struct {
142 int x, y;
143 } start, stop;
144 Eina_List *distances;
145 enum ruler_type type;
146};
147
148static Eina_Bool
149theme_apply(Evas_Object *edje, const char *group)
150{
151 const char *errmsg;
152
153 EINA_SAFETY_ON_NULL_RETURN_VAL(edje, EINA_FALSE);
154 EINA_SAFETY_ON_NULL_RETURN_VAL(group, EINA_FALSE);
155
156 if (edje_object_file_set(edje, theme_file, group))
157 return EINA_TRUE;
158
159 errmsg = edje_load_error_str(edje_object_load_error_get(edje));
160 CRI("Cannot find theme: file=%s group=%s error='%s'",
161 theme_file, group, errmsg);
162 return EINA_FALSE;
163}
164
165static void
166show_guides_apply(void)
167{
168 const Eina_List *l;
169 const Zone *zone;
170
171 EINA_LIST_FOREACH(zones, l, zone)
172 {
173 elm_check_state_set(zone->gui.show_guides, show_guides);
174 }
175}
176
177static void
178show_distances_apply(void)
179{
180 const Eina_List *l;
181 const Zone *zone;
182
183 EINA_LIST_FOREACH(zones, l, zone)
184 {
185 if (show_distances && zone->distances)
186 evas_object_show(zone->group.distances);
187 else
188 evas_object_hide(zone->group.distances);
189 elm_check_state_set(zone->gui.show_distances,
190 show_distances);
191 }
192}
193
194static Ruler_Data *
195ruler_data_get(const Evas_Object *o)
196{
197 return evas_object_data_get(o, "ruler_data");
198}
199
200static Evas_Object *
201zone_ruler_last_get(const Zone *zone)
202{
203 return eina_list_data_get(eina_list_last(zone->rulers));
204}
205
206static void distance_update(Distance *d);
207
208static void
209_ruler_distances_update(Evas_Object *ruler)
210{
211 Ruler_Data *rd = ruler_data_get(ruler);
212 const Eina_List *l;
213 Distance *d;
214
215 EINA_LIST_FOREACH(rd->distances, l, d)
216 distance_update(d);
217}
218
219static void
220zone_last_ruler_used_set(Zone *zone, Eina_Bool used)
221{
222 Evas_Object *ruler;
223
224 zone->last_ruler_used = used;
225 ruler = zone_ruler_last_get(zone);
226 _ruler_distances_update(ruler);
227
228 if (zone->gui.frame)
229 {
230 elm_object_disabled_set(zone->gui.create, !used);
231
232 if ((!used) && (eina_list_count(zone->rulers) == 1))
233 elm_object_disabled_set(zone->gui.clear, EINA_TRUE);
234 else if (eina_list_count(zone->rulers) > 1)
235 elm_object_disabled_set(zone->gui.clear, EINA_FALSE);
236 else
237 elm_object_disabled_set(zone->gui.clear, !used);
238 }
239}
240
241static void
242zone_rulers_clear(Zone *zone)
243{
244 Evas_Object *ruler;
245 EINA_LIST_FREE(zone->rulers, ruler)
246 evas_object_del(ruler);
247}
248
249static void
250_ruler_state_update(Evas_Object *ruler)
251{
252 const Ruler_Data *rd = ruler_data_get(ruler);
253 Edje_Message_Int_Set *msg;
254 int x, y, w, h, dx, dy;
255
256 x = rd->start.x;
257 y = rd->start.y;
258 dx = w = rd->stop.x - rd->start.x;
259 dy = h = rd->stop.y - rd->start.y;
260
261 if (w < 0)
262 {
263 w = -w;
264 x -= w;
265 }
266
267 if (h < 0)
268 {
269 h = -h;
270 y -= h;
271 }
272
273 w++;
274 h++;
275
276 dx = dx < 0 ? -w : w;
277 dy = dy < 0 ? -h : h;
278
279 evas_object_move(ruler, x, y);
280 evas_object_resize(ruler, w, h);
281
282 msg = alloca(sizeof(Edje_Message_Int_Set) + sizeof(int));
283 msg->count = 2;
284 msg->val[0] = rd->start.x;
285 msg->val[1] = rd->start.y;
286 edje_object_message_send(ruler, EDJE_MESSAGE_INT_SET, 0, msg);
287
288 msg->val[0] = dx;
289 msg->val[1] = dy;
290 edje_object_message_send(ruler, EDJE_MESSAGE_INT_SET, 1, msg);
291}
292
293static void _zone_gui_style_label_update(Zone *zone);
294
295static void
296ruler_type_apply(Evas_Object *ruler)
297{
298 Ruler_Data *rd = ruler_data_get(ruler);
299 char buf[128];
300
301 eina_strlcpy(buf, RULER_TYPE_PREFIX, sizeof(buf));
302 eina_strlcat(buf, ruler_type_names_strs[rd->type], sizeof(buf));
303 theme_apply(ruler, buf);
304 _ruler_state_update(ruler);
305
306 if (rd->zone)
307 _zone_gui_style_label_update(rd->zone);
308}
309
310static void
311ruler_move_relative(Evas_Object *ruler, int dx, int dy)
312{
313 Ruler_Data *rd;
314
315 DBG("place ruler %p relative by %d, %d", ruler, dx, dy);
316
317 rd = ruler_data_get(ruler);
318 rd->start.x += dx;
319 rd->start.y += dy;
320 rd->stop.x += dx;
321 rd->stop.y += dy;
322
323 _ruler_state_update(ruler);
324 evas_object_show(ruler);
325}
326
327static void
328ruler_resize_relative(Evas_Object *ruler, int dw, int dh)
329{
330 Ruler_Data *rd;
331
332 DBG("resize ruler %p relative by %d, %d", ruler, dw, dh);
333
334 rd = ruler_data_get(ruler);
335
336 rd->stop.x += dw;
337 rd->stop.y += dh;
338
339 _ruler_state_update(ruler);
340 evas_object_show(ruler);
341}
342
343static void
344ruler_place(Evas_Object *ruler, int x, int y, int w, int h)
345{
346 Ruler_Data *rd;
347
348 DBG("place ruler %p at %d,%d size %dx%d", ruler, x, y, w, h);
349
350 rd = ruler_data_get(ruler);
351 rd->start.x = x;
352 rd->start.y = y;
353 rd->stop.x = x + w - 1;
354 rd->stop.y = y + h - 1;
355
356 _ruler_state_update(ruler);
357 evas_object_show(ruler);
358}
359
360static Eina_Bool
361_event_mouse_tracker(void *data)
362{
363 Zone *zone = data;
364 Evas_Coord x, y, dx, dy, dw, dh, gx, gy, gw, gh;
365 char buf[64];
366
367 if (zone->screenshot.ee) return EINA_TRUE;
368
369 evas_pointer_canvas_xy_get(zone->evas, &x, &y);
370 if ((x < 0) || (x >= zone->w) || (y < 0) || (y >= zone->h))
371 return EINA_TRUE;
372
373 if ((x == zone->last_mouse.x) && (y == zone->last_mouse.y))
374 return EINA_TRUE;
375 zone->last_mouse.x = x;
376 zone->last_mouse.y = y;
377
378 evas_object_geometry_get(zone->gui.frame, &gx, &gy, &gw, &gh);
379 if (((x >= gx) && (x < gx + gw)) &&
380 ((y >= gy) && (y < gy + gh)))
381 {
382 evas_object_hide(zone->display_pos);
383 evas_object_hide(zone->guide_v);
384 evas_object_hide(zone->guide_h);
385 if (zone->zoom.frame)
386 evas_object_hide(zone->zoom.frame);
387 return EINA_TRUE;
388 }
389 evas_object_show(zone->display_pos);
390
391 if (zone->handling)
392 {
393 Ruler_Data *rd = ruler_data_get(zone->handling);
394 rd->stop.x = x;
395 rd->stop.y = y;
396 _ruler_state_update(zone->handling);
397 evas_object_show(zone->handling);
398 }
399
400 if (show_guides)
401 {
402 evas_object_move(zone->guide_v, x, 0);
403 evas_object_resize(zone->guide_v, 1, zone->h);
404 evas_object_show(zone->guide_v);
405
406 evas_object_move(zone->guide_h, 0, y);
407 evas_object_resize(zone->guide_h, zone->w, 1);
408 evas_object_show(zone->guide_h);
409 }
410
411 snprintf(buf, sizeof(buf), "%d,%d", x, y);
412 edje_object_part_text_set(zone->display_pos, "text", buf);
413 edje_object_size_min_calc(zone->display_pos, &dw, &dh);
414 dx = x - dw - 10;
415 if (dx < 0)
416 dx = x + 10;
417 dy = y - dh - 10;
418 if (dy < 0)
419 dy = y + 10;
420 evas_object_move(zone->display_pos, dx, dy);
421 evas_object_resize(zone->display_pos, dw, dh);
422
423 if (zone->zoom.ready)
424 {
425 int fx, fy, fw, fh, zx, zy, zw, zh, stride, iw, ih;
426 unsigned int *pixels, color;
427 char buf[32];
428
429 zw = zone->zoom.ideal_size.w < zone->w / 4 ?
430 zone->zoom.ideal_size.w : zone->w / 4;
431 zh = zone->zoom.ideal_size.h < zone->h / 4 ?
432 zone->zoom.ideal_size.h : zone->h / 4;
433
434 fx = -x * zone->zoom.factor + zw / 2 - zone->zoom.factor / 2;
435 fy = -y * zone->zoom.factor + zh / 2 - zone->zoom.factor / 2;
436 fw = zone->w * zone->zoom.factor;
437 fh = zone->h * zone->zoom.factor;
438
439 zx = x + 10;
440 zy = y + 10;
441
442 if (zx + zw > zone->w)
443 zx = dx - zw - 10;
444
445 if (zy + zh > zone->h)
446 zy = dy - zh - 10;
447
448 evas_object_move(zone->zoom.frame, zx, zy);
449 evas_object_resize(zone->zoom.frame, zw, zh);
450 evas_object_image_fill_set(zone->zoom.image, fx, fy, fw, fh);
451
452 pixels = evas_object_image_data_get(zone->zoom.image, EINA_FALSE);
453 stride = evas_object_image_stride_get(zone->zoom.image);
454 evas_object_image_size_get(zone->zoom.image, &iw, &ih);
455
456 EINA_SAFETY_ON_NULL_RETURN_VAL(pixels, EINA_TRUE);
457
458 EINA_SAFETY_ON_FALSE_GOTO(x >= 0, position_invalid);
459 EINA_SAFETY_ON_FALSE_GOTO(y >= 0, position_invalid);
460 EINA_SAFETY_ON_FALSE_GOTO(x < iw, position_invalid);
461 EINA_SAFETY_ON_FALSE_GOTO(y < ih, position_invalid);
462
463 color = pixels[y * (stride / sizeof(unsigned int)) + x];
464 color = color & 0xffffff;
465 if (hex_colors)
466 snprintf(buf, sizeof(buf), "#%06x", color);
467 else
468 {
469 snprintf(buf, sizeof(buf), "%d %d %d",
470 (color >> 16) & 0xff,
471 (color >> 8) & 0xff,
472 (color & 0xff));
473 }
474 edje_object_part_text_set(zone->zoom.frame, "color", buf);
475
476 position_invalid:
477 evas_object_image_data_set(zone->zoom.image, pixels);
478 evas_object_show(zone->zoom.frame);
479 }
480
481 return EINA_TRUE;
482}
483
484static void
485_handling_start(Zone *zone)
486{
487 Evas_Object *ruler;
488 Ruler_Data *rd;
489 Edje_Message_Int_Set *msg;
490
491 ruler = zone_ruler_last_get(zone);
492 EINA_SAFETY_ON_NULL_RETURN(ruler);
493
494 zone->handling = ruler;
495
496 rd = ruler_data_get(ruler);
497
498 zone_last_ruler_used_set(zone, EINA_TRUE);
499
500 evas_pointer_canvas_xy_get(zone->evas, &rd->start.x, &rd->start.y);
501 evas_object_move(ruler, rd->start.x, rd->start.y);
502 evas_object_show(ruler);
503
504 msg = alloca(sizeof(Edje_Message_Int_Set) + sizeof(int));
505 msg->count = 2;
506 msg->val[0] = rd->start.x;
507 msg->val[1] = rd->start.y;
508 edje_object_message_send(ruler, EDJE_MESSAGE_INT_SET, 0, msg);
509
510 zone->last_mouse.x = -1;
511 zone->last_mouse.y = -1;
512 _event_mouse_tracker(zone);
513}
514
515static void
516_handling_stop(Zone *zone)
517{
518 zone->handling = NULL;
519}
520
521static void
522_event_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *o EINA_UNUSED, void *event)
523{
524 Zone *zone = data;
525 Evas_Event_Mouse_Down *ev = event;
526
527 if (zone->handling)
528 return;
529
530 if (ev->button != 1)
531 return;
532
533 if (zone->cmdbox)
534 evas_object_del(zone->cmdbox);
535
536 zone->keyboard_move = EINA_FALSE;
537 _handling_start(zone);
538}
539
540static void
541_event_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *o EINA_UNUSED, void *event EINA_UNUSED)
542{
543 Zone *zone = data;
544 _handling_stop(zone);
545}
546
547static void
548_event_del(void *data, Evas *e EINA_UNUSED, Evas_Object *o EINA_UNUSED, void *event EINA_UNUSED)
549{
550 Zone *zone = data;
551 if (zone->tracker)
552 {
553 ecore_animator_del(zone->tracker);
554 zone->tracker = NULL;
555 }
556
557 zone_rulers_clear(zone);
558}
559
560static void
561zone_hint_setup(Zone *zone)
562{
563 zone->hint = edje_object_add(zone->evas);
564 if (!theme_apply(zone->hint, "eruler/hint"))
565 return;
566 evas_object_repeat_events_set(zone->hint, EINA_TRUE);
567 evas_object_show(zone->hint);
568
569 edje_object_part_text_set(zone->hint, "hint",
570 "<title>ERuler</><br>"
571 "Press <hilight>F1</hilight> for help or "
572 "<hilight>Escape</hilight> to quit.");
573
574 evas_object_size_hint_weight_set(zone->hint,
575 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
576 evas_object_size_hint_align_set(zone->hint, EVAS_HINT_FILL, EVAS_HINT_FILL);
577 elm_win_resize_object_add(zone->win, zone->hint);
578
579 zone->guide_h = evas_object_rectangle_add(zone->evas);
580 evas_object_pass_events_set(zone->guide_h, EINA_TRUE);
581 evas_object_color_set(zone->guide_h, 128, 0, 0, 128);
582
583 zone->guide_v = evas_object_rectangle_add(zone->evas);
584 evas_object_pass_events_set(zone->guide_v, EINA_TRUE);
585 evas_object_color_set(zone->guide_v, 128, 0, 0, 128);
586
587 zone->display_pos = edje_object_add(zone->evas);
588 if (!theme_apply(zone->display_pos, "eruler/display_pos"))
589 return;
590 evas_object_pass_events_set(zone->display_pos, EINA_TRUE);
591 evas_object_show(zone->display_pos);
592}
593
594static void
595_ruler_free(void *data, Evas *e EINA_UNUSED, Evas_Object *o EINA_UNUSED, void *event EINA_UNUSED)
596{
597 Ruler_Data *rd = data;
598 eina_list_free(rd->distances);
599 free(rd);
600}
601
602static void
603_distance_source_changed(void *data, Evas *e EINA_UNUSED, Evas_Object *o EINA_UNUSED, void *event EINA_UNUSED)
604{
605 Distance *d = data;
606 distance_update(d);
607}
608
609static void
610distance_update(Distance *d)
611{
612 int ax1, ay1, ax2, ay2, aw, ah;
613 int bx1, by1, bx2, by2, bw, bh;
614 int x, y, w, h;
615 char buf[32];
616
617 if (!d->zone->last_ruler_used)
618 {
619 Evas_Object *last = zone_ruler_last_get(d->zone);
620 if ((last == d->a) || (last == d->b))
621 {
622 DBG("Hide distance to unused ruler %p (a: %p, b: %p)",
623 last, d->a, d->b);
624 evas_object_hide(d->top);
625 evas_object_hide(d->bottom);
626 evas_object_hide(d->left);
627 evas_object_hide(d->right);
628 return;
629 }
630 }
631
632 evas_object_geometry_get(d->a, &ax1, &ay1, &aw, &ah);
633 evas_object_geometry_get(d->b, &bx1, &by1, &bw, &bh);
634
635 ax2 = ax1 + aw;
636 ay2 = ay1 + ah;
637
638 bx2 = bx1 + bw;
639 by2 = by1 + bh;
640
641 /* horizontal distances */
642 if (ax2 < bx1)
643 {
644 x = ax2;
645 w = bx1 - ax2;
646 }
647 else if (ax1 > bx2)
648 {
649 x = bx2;
650 w = ax1 - bx2;
651 }
652 else
653 {
654 int x2 = ax2 < bx2 ? ax2 : bx2; /* the left one */
655 x = ax1 < bx1 ? bx1 : ax1; /* the right one */
656 w = x2 - x;
657 }
658
659 if (ay2 < by1)
660 {
661 evas_object_hide(d->top);
662 evas_object_move(d->bottom, x, ay2);
663 evas_object_resize(d->bottom, w, (by1 - ay2));
664 snprintf(buf, sizeof(buf), "%d", (by1 - ay2));
665 edje_object_part_text_set(d->bottom, "display", buf);
666 evas_object_show(d->bottom);
667 }
668 else if (ay1 > by2)
669 {
670 evas_object_hide(d->bottom);
671 evas_object_move(d->top, x, by2);
672 evas_object_resize(d->top, w, (ay1 - by2));
673 snprintf(buf, sizeof(buf), "%d", (ay1 - by2));
674 edje_object_part_text_set(d->top, "display", buf);
675 evas_object_show(d->top);
676 }
677 else
678 {
679 if (ay1 < by1)
680 {
681 y = ay1;
682 h = by1 - ay1 + 1;
683 }
684 else
685 {
686 y = by1;
687 h = ay1 - by1 + 1;
688 }
689 evas_object_move(d->top, x, y);
690 evas_object_resize(d->top, w, h);
691 snprintf(buf, sizeof(buf), "%d", h);
692 edje_object_part_text_set(d->top, "display", buf);
693 evas_object_show(d->top);
694
695 if (ay2 < by2)
696 {
697 y = ay2;
698 h = by2 - ay2 + 1;
699 }
700 else
701 {
702 y = by2;
703 h = ay2 - by2 + 1;
704 }
705 evas_object_move(d->bottom, x, y);
706 evas_object_resize(d->bottom, w, h);
707 snprintf(buf, sizeof(buf), "%d", h);
708 edje_object_part_text_set(d->bottom, "display", buf);
709 evas_object_show(d->bottom);
710 }
711
712 /* horizontal distances */
713 if (ay2 < by1)
714 {
715 y = ay2;
716 h = by1 - ay2;
717 }
718 else if (ay1 > by2)
719 {
720 y = by2;
721 h = ay1 - by2;
722 }
723 else
724 {
725 int y2 = ay2 < by2 ? ay2 : by2; /* the top one */
726 y = ay1 < by1 ? by1 : ay1; /* the bottom one */
727 h = y2 - y;
728 }
729
730 if (ax2 < bx1)
731 {
732 evas_object_hide(d->left);
733 evas_object_move(d->right, ax2, y);
734 evas_object_resize(d->right, (bx1 - ax2), h);
735 snprintf(buf, sizeof(buf), "%d", (bx1 - ax2));
736 edje_object_part_text_set(d->right, "display", buf);
737 evas_object_show(d->right);
738 }
739 else if (ax1 > bx2)
740 {
741 evas_object_hide(d->right);
742 evas_object_move(d->left, bx2, y);
743 evas_object_resize(d->left, (ax1 - bx2), h);
744 snprintf(buf, sizeof(buf), "%d", (ax1 - bx2));
745 edje_object_part_text_set(d->left, "display", buf);
746 evas_object_show(d->left);
747 }
748 else
749 {
750 if (ax1 < bx1)
751 {
752 x = ax1;
753 w = bx1 - ax1 + 1;
754 }
755 else
756 {
757 x = bx1;
758 w = ax1 - bx1 + 1;
759 }
760 evas_object_move(d->left, x, y);
761 evas_object_resize(d->left, w, h);
762 snprintf(buf, sizeof(buf), "%d", w);
763 edje_object_part_text_set(d->left, "display", buf);
764 evas_object_show(d->left);
765
766 if (ax2 < bx2)
767 {
768 x = ax2;
769 w = bx2 - ax2 + 1;
770 }
771 else
772 {
773 x = bx2;
774 w = ax2 - bx2 + 1;
775 }
776 evas_object_move(d->right, x, y);
777 evas_object_resize(d->right, w, h);
778 snprintf(buf, sizeof(buf), "%d", w);
779 edje_object_part_text_set(d->right, "display", buf);
780 evas_object_show(d->right);
781 }
782}
783
784static void _distance_source_del(void *data, Evas *e EINA_UNUSED, Evas_Object *o, void *event EINA_UNUSED);
785
786static void
787distance_del(Distance *d)
788{
789 Ruler_Data *rd;
790 Zone *zone = d->zone;
791
792 /* 'a' or 'b' may have vanished (_distance_source_del) and will be NULL */
793
794 if (d->a)
795 {
796 rd = ruler_data_get(d->a);
797 rd->distances = eina_list_remove(rd->distances, d);
798
799 evas_object_event_callback_del_full(d->a, EVAS_CALLBACK_DEL,
800 _distance_source_del, d);
801 evas_object_event_callback_del_full(d->a, EVAS_CALLBACK_MOVE,
802 _distance_source_changed, d);
803 evas_object_event_callback_del_full(d->a, EVAS_CALLBACK_RESIZE,
804 _distance_source_changed, d);
805 }
806
807 if (d->b)
808 {
809 rd = ruler_data_get(d->b);
810 rd->distances = eina_list_remove(rd->distances, d);
811
812 evas_object_event_callback_del_full(d->b, EVAS_CALLBACK_DEL,
813 _distance_source_del, d);
814 evas_object_event_callback_del_full(d->b, EVAS_CALLBACK_MOVE,
815 _distance_source_changed, d);
816 evas_object_event_callback_del_full(d->b, EVAS_CALLBACK_RESIZE,
817 _distance_source_changed, d);
818 }
819
820 evas_object_del(d->top);
821 evas_object_del(d->bottom);
822 evas_object_del(d->left);
823 evas_object_del(d->right);
824
825 zone->distances = eina_list_remove(zone->distances, d);
826 free(d);
827
828 if (!zone->distances)
829 evas_object_hide(zone->group.distances);
830}
831
832static void
833_distance_source_del(void *data, Evas *e EINA_UNUSED, Evas_Object *o, void *event EINA_UNUSED)
834{
835 Distance *d = data;
836
837 /* if we delete 'a' we need to stop monitoring 'b' to avoid double free
838 * and remove from 'b' distances to not mess with deleted distance
839 */
840 if (o == d->a)
841 d->a = NULL;
842 else
843 d->b = NULL;
844
845 distance_del(d);
846}
847
848static void
849distance_create(Zone *zone, Evas_Object *a, Evas_Object *b)
850{
851 Ruler_Data *rd;
852 Distance *d;
853
854 d = calloc(1, sizeof(Distance));
855 EINA_SAFETY_ON_NULL_RETURN(d);
856
857 d->zone = zone;
858 d->a = a;
859 d->b = b;
860
861 evas_object_event_callback_add(a, EVAS_CALLBACK_DEL,
862 _distance_source_del, d);
863 evas_object_event_callback_add(a, EVAS_CALLBACK_MOVE,
864 _distance_source_changed, d);
865 evas_object_event_callback_add(a, EVAS_CALLBACK_RESIZE,
866 _distance_source_changed, d);
867
868 rd = ruler_data_get(d->a);
869 rd->distances = eina_list_append(rd->distances, d);
870
871 evas_object_event_callback_add(b, EVAS_CALLBACK_DEL,
872 _distance_source_del, d);
873 evas_object_event_callback_add(b, EVAS_CALLBACK_MOVE,
874 _distance_source_changed, d);
875 evas_object_event_callback_add(b, EVAS_CALLBACK_RESIZE,
876 _distance_source_changed, d);
877 rd = ruler_data_get(d->b);
878 rd->distances = eina_list_append(rd->distances, d);
879
880 /* clipper was hidden if clipping nothing */
881 if ((!zone->distances) && (show_distances))
882 evas_object_show(zone->group.distances);
883
884 zone->distances = eina_list_append(zone->distances, d);
885
886 d->top = edje_object_add(zone->evas);
887 theme_apply(d->top, "eruler/distance_vertical");
888 evas_object_smart_member_add(d->top, zone->group.distances);
889
890 d->bottom = edje_object_add(zone->evas);
891 theme_apply(d->bottom, "eruler/distance_vertical");
892 evas_object_smart_member_add(d->bottom, zone->group.distances);
893
894 d->left = edje_object_add(zone->evas);
895 theme_apply(d->left, "eruler/distance_horizontal");
896 evas_object_smart_member_add(d->left, zone->group.distances);
897
898 d->right = edje_object_add(zone->evas);
899 theme_apply(d->right, "eruler/distance_horizontal");
900 evas_object_smart_member_add(d->right, zone->group.distances);
901}
902
903static void
904zone_ruler_create(Zone *zone)
905{
906 Evas_Object *ruler;
907 Ruler_Data *rd;
908
909 rd = calloc(1, sizeof(Ruler_Data));
910 EINA_SAFETY_ON_NULL_RETURN(rd);
911
912 rd->zone = zone;
913 ruler = edje_object_add(zone->evas);
914 evas_object_smart_member_add(ruler, zone->group.rulers);
915 evas_object_event_callback_add(ruler, EVAS_CALLBACK_FREE,
916 _ruler_free, rd);
917 evas_object_pass_events_set(ruler, EINA_TRUE);
918 evas_object_data_set(ruler, "ruler_data", rd);
919 rd->type = initial_ruler_type;
920
921 if (zone->rulers)
922 {
923 Evas_Object *other;
924 Eina_List *l;
925 EINA_LIST_FOREACH(zone->rulers, l, other)
926 distance_create(zone, other, ruler);
927 }
928
929 zone->rulers = eina_list_append(zone->rulers, ruler);
930
931 ruler_type_apply(ruler);
932 zone_last_ruler_used_set(zone, EINA_FALSE);
933}
934
935static void
936zone_ruler_setup(Zone *zone)
937{
938 zone->event = evas_object_rectangle_add(zone->evas);
939 evas_object_color_set(zone->event, 0, 0, 0, 0);
940 evas_object_repeat_events_set(zone->event, EINA_TRUE);
941 evas_object_show(zone->event);
942
943 evas_object_event_callback_add(zone->event, EVAS_CALLBACK_MOUSE_DOWN,
944 _event_mouse_down, zone);
945 evas_object_event_callback_add(zone->event, EVAS_CALLBACK_MOUSE_UP,
946 _event_mouse_up, zone);
947 evas_object_event_callback_add(zone->event, EVAS_CALLBACK_DEL,
948 _event_del, zone);
949 evas_object_size_hint_weight_set(zone->event,
950 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
951 evas_object_size_hint_align_set(zone->event, EVAS_HINT_FILL, EVAS_HINT_FILL);
952 elm_win_resize_object_add(zone->win, zone->event);
953
954 zone->group.distances = group_add(zone->evas);
955 evas_object_size_hint_weight_set(zone->group.distances,
956 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
957 evas_object_size_hint_align_set(zone->group.distances,
958 EVAS_HINT_FILL, EVAS_HINT_FILL);
959 elm_win_resize_object_add(zone->win, zone->group.distances);
960
961 zone->group.rulers = group_add(zone->evas);
962 evas_object_size_hint_weight_set(zone->group.rulers,
963 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
964 evas_object_size_hint_align_set(zone->group.rulers,
965 EVAS_HINT_FILL, EVAS_HINT_FILL);
966 elm_win_resize_object_add(zone->win, zone->group.rulers);
967 evas_object_show(zone->group.rulers);
968
969 zone_ruler_create(zone);
970
971 zone->tracker = ecore_animator_add(_event_mouse_tracker, zone);
972}
973
974static void
975_zone_gui_resize_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *o EINA_UNUSED, void *event EINA_UNUSED)
976{
977 Zone *zone = data;
978 int x, y, w, h;
979
980 evas_object_geometry_get(zone->gui.frame, &x, &y, NULL, NULL);
981 evas_object_size_hint_min_get(zone->gui.frame, &w, &h);
982
983 if (x + w > zone->w - 10)
984 x = zone->w - 10 - w;
985
986 if (y + h > zone->h - 10)
987 y = zone->h - 10 - h;
988
989 if (x < 10)
990 x = 10;
991 if (y < 10)
992 y = 10;
993
994 evas_object_move(zone->gui.frame, x, y);
995 evas_object_resize(zone->gui.frame, w, h);
996}
997
998static void
999_zone_gui_create(void *data, Evas_Object *o EINA_UNUSED, void *event EINA_UNUSED)
1000{
1001 Zone *zone = data;
1002 if (zone->last_ruler_used)
1003 zone_ruler_create(zone);
1004}
1005
1006static void
1007_zone_gui_clear(void *data, Evas_Object *o EINA_UNUSED, void *event EINA_UNUSED)
1008{
1009 Zone *zone = data;
1010 zone_rulers_clear(zone);
1011 zone_ruler_create(zone);
1012}
1013
1014static void create_ruler_from_cmdbox(Zone *zone);
1015static void
1016_zone_gui_type(void *data, Evas_Object *o EINA_UNUSED, void *event EINA_UNUSED)
1017{
1018 Zone *zone = data;
1019 create_ruler_from_cmdbox(zone);
1020}
1021
1022static void
1023_zone_gui_style_label_update(Zone *zone)
1024{
1025 Evas_Object *ruler;
1026 Ruler_Data *rd;
1027 char buf[128];
1028
1029 if (!zone->gui.style) return;
1030
1031 ruler = zone_ruler_last_get(zone);
1032 rd = ruler_data_get(ruler);
1033 snprintf(buf, sizeof(buf), "Style: %s", ruler_type_names_strs[rd->type]);
1034 elm_object_text_set(zone->gui.style, buf);
1035}
1036
1037static void
1038_zone_gui_style_changed(void *data, Evas_Object *o EINA_UNUSED, void *event)
1039{
1040 Zone *zone = data;
1041 Evas_Object *ruler;
1042 Ruler_Data *rd;
1043 Elm_Object_Item *it = event;
1044 const char *style = elm_object_item_text_get(it);
1045 unsigned int i;
1046
1047 for (i = 0; ruler_type_names_strs[i] != NULL; i++)
1048 {
1049 if (strcmp(ruler_type_names_strs[i], style) == 0)
1050 break;
1051 }
1052
1053 EINA_SAFETY_ON_NULL_RETURN(ruler_type_names_strs[i]);
1054
1055 ruler = zone_ruler_last_get(zone);
1056 EINA_SAFETY_ON_NULL_RETURN(ruler);
1057 rd = ruler_data_get(ruler);
1058
1059 rd->type = i;
1060 ruler_type_apply(ruler);
1061}
1062
1063static void zone_zoom_pre_setup(Zone *zone);
1064static void _zone_screen_copy_cb(void *data, Eina_Bool success);
1065
1066static void
1067_zone_gui_zoom_changed(void *data, Evas_Object *o, void *event EINA_UNUSED)
1068{
1069 Zone *zone = data;
1070 Eina_Bool state = elm_check_state_get(o);
1071
1072 if (state)
1073 {
1074 if (!zone->zoom.image)
1075 {
1076 zone_zoom_pre_setup(zone);
1077 platform_funcs->zone_screen_copy(zone, zone->zoom.image,
1078 _zone_screen_copy_cb,
1079 zone);
1080 }
1081 }
1082 else
1083 {
1084 if (zone->zoom.image)
1085 {
1086 evas_object_del(zone->zoom.image);
1087 zone->zoom.image = NULL;
1088 evas_object_del(zone->zoom.frame);
1089 zone->zoom.frame = NULL;
1090 zone->zoom.ready = EINA_FALSE;
1091 }
1092 }
1093}
1094
1095static void
1096_zone_gui_show_hex_colors_changed(void *data EINA_UNUSED, Evas_Object *o, void *event EINA_UNUSED)
1097{
1098 Eina_Bool state = elm_check_state_get(o);
1099 hex_colors = state;
1100}
1101
1102static void
1103_zone_gui_show_guides_changed(void *data EINA_UNUSED, Evas_Object *o, void *event EINA_UNUSED)
1104{
1105 Eina_Bool state = elm_check_state_get(o);
1106 show_guides = state;
1107 show_guides_apply();
1108}
1109
1110static void
1111_zone_gui_show_distances_changed(void *data EINA_UNUSED, Evas_Object *o, void *event EINA_UNUSED)
1112{
1113 Eina_Bool state = elm_check_state_get(o);
1114 show_distances = state;
1115 show_distances_apply();
1116}
1117
1118static void show_gui_help(Zone *zone);
1119static void
1120_zone_gui_help(void *data, Evas_Object *o EINA_UNUSED, void *event EINA_UNUSED)
1121{
1122 Zone *zone = data;
1123 show_gui_help(zone);
1124}
1125
1126static void
1127_zone_gui_exit(void *data EINA_UNUSED, Evas_Object *o EINA_UNUSED, void *event EINA_UNUSED)
1128{
1129 elm_exit();
1130}
1131
1132static void create_screenshot(Zone *zone);
1133static void
1134_zone_gui_shot(void *data, Evas_Object *o EINA_UNUSED, void *event EINA_UNUSED)
1135{
1136 Zone *zone = data;
1137 create_screenshot(zone);
1138}
1139
1140static void
1141_zone_gui_widget_setup(Evas_Object *o)
1142{
1143 evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0);
1144 evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.0);
1145 elm_object_focus_allow_set(o, EINA_FALSE);
1146}
1147
1148static void
1149_zone_gui_icon_set(Evas_Object *o, const char *part, const char *iconname)
1150{
1151 Evas_Object *ic = elm_icon_add(o);
1152
1153 if (!elm_icon_standard_set(ic, iconname))
1154 {
1155 evas_object_del(ic);
1156 return;
1157 }
1158
1159 elm_object_part_content_set(o, part, ic);
1160}
1161
1162static Evas_Object *
1163_zone_gui_check_add(Zone *zone, Eina_Bool state, const char *label, Evas_Smart_Cb cb)
1164{
1165 Evas_Object *ck = elm_check_add(zone->gui.main_box);
1166 _zone_gui_widget_setup(ck);
1167 elm_object_text_set(ck, label);
1168 elm_check_state_set(ck, state);
1169 evas_object_smart_callback_add(ck, "changed", cb, zone);
1170 evas_object_show(ck);
1171 elm_box_pack_end(zone->gui.main_box, ck);
1172 return ck;
1173}
1174
1175static Evas_Object *
1176_zone_gui_button_add(Zone *zone, const char *icon, const char *label, Evas_Smart_Cb cb)
1177{
1178 Evas_Object *bt = elm_button_add(zone->gui.main_box);
1179 _zone_gui_widget_setup(bt);
1180 _zone_gui_icon_set(bt, NULL, icon);
1181 elm_object_text_set(bt, label);
1182 evas_object_smart_callback_add(bt, "clicked", cb, zone);
1183 evas_object_show(bt);
1184 elm_box_pack_end(zone->gui.main_box, bt);
1185 return bt;
1186}
1187
1188static Eina_Bool
1189_zone_gui_frame_moving(void *data)
1190{
1191 Zone *zone = data;
1192 int x, y, w, h;
1193
1194 evas_pointer_canvas_xy_get(zone->evas, &x, &y);
1195 evas_object_size_hint_min_get(zone->gui.frame, &w, &h);
1196
1197 x -= zone->gui.moving.dx;
1198 y -= zone->gui.moving.dy;
1199
1200 if (x + w > zone->w - 10)
1201 x = zone->w - 10 - w;
1202
1203 if (y + h > zone->h - 10)
1204 y = zone->h - 10 - h;
1205
1206 if (x < 10)
1207 x = 10;
1208 if (y < 10)
1209 y = 10;
1210
1211 evas_object_move(zone->gui.frame, x, y);
1212 evas_object_resize(zone->gui.frame, w, h);
1213
1214 return EINA_TRUE;
1215}
1216
1217static void
1218_zone_gui_frame_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *o, void *event)
1219{
1220 Zone *zone = data;
1221 Evas_Event_Mouse_Down *ev = event;
1222 int x, y;
1223
1224 if ((zone->gui.moving.anim) || (ev->button != 1))
1225 return;
1226
1227 if (!elm_frame_collapse_get(o))
1228 {
1229 int bx, by, bw, bh;
1230 evas_object_geometry_get(zone->gui.main_box, &bx, &by, &bw, &bh);
1231 if (((ev->canvas.x >= bx) && (ev->canvas.x < bx + bw)) &&
1232 ((ev->canvas.y >= by) && (ev->canvas.y < by + bh)))
1233 return;
1234 }
1235
1236 evas_object_geometry_get(o, &x, &y, NULL, NULL);
1237
1238 zone->gui.moving.x = ev->canvas.x;
1239 zone->gui.moving.y = ev->canvas.y;
1240 zone->gui.moving.dx = ev->canvas.x - x;
1241 zone->gui.moving.dy = ev->canvas.y - y;
1242 zone->gui.moving.anim = ecore_animator_add(_zone_gui_frame_moving, zone);
1243}
1244
1245static void
1246_zone_gui_frame_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *o, void *event)
1247{
1248 Zone *zone = data;
1249 Evas_Event_Mouse_Up *ev = event;
1250 int fingersize, dx, dy;
1251
1252 if ((!zone->gui.moving.anim) || (ev->button != 1))
1253 return;
1254
1255 fingersize = elm_config_finger_size_get();
1256
1257 dx = zone->gui.moving.x - ev->canvas.x;
1258 dy = zone->gui.moving.y - ev->canvas.y;
1259
1260 if (dx < 0)
1261 dx = -dx;
1262 if (dy < 0)
1263 dy = -dy;
1264
1265 if ((dx < fingersize) && (dy < fingersize))
1266 {
1267 evas_object_move(o, zone->gui.moving.x - zone->gui.moving.dx,
1268 zone->gui.moving.y - zone->gui.moving.dy);
1269 elm_frame_collapse_set(o, !elm_frame_collapse_get(o));
1270 }
1271
1272 zone->gui.moving.x = 0;
1273 zone->gui.moving.y = 0;
1274 zone->gui.moving.dx = 0;
1275 zone->gui.moving.dy = 0;
1276 ecore_animator_del(zone->gui.moving.anim);
1277 zone->gui.moving.anim = NULL;
1278}
1279
1280static void
1281zone_gui_setup(Zone *zone)
1282{
1283 Evas_Object *o;
1284 unsigned int i;
1285
1286 zone->gui.frame = elm_frame_add(zone->win);
1287 elm_object_focus_allow_set(zone->gui.frame, EINA_FALSE);
1288 evas_object_event_callback_add(zone->gui.frame,
1289 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1290 _zone_gui_resize_cb, zone);
1291 if (eina_list_count(zones) == 1)
1292 elm_object_text_set(zone->gui.frame, "ERuler");
1293 else
1294 {
1295 char buf[128];
1296 snprintf(buf, sizeof(buf), "ERuler (Zone #%d)", zone->idx);
1297 elm_object_text_set(zone->gui.frame, buf);
1298 }
1299
1300 evas_object_event_callback_add(zone->gui.frame, EVAS_CALLBACK_MOUSE_DOWN,
1301 _zone_gui_frame_mouse_down, zone);
1302 evas_object_event_callback_add(zone->gui.frame, EVAS_CALLBACK_MOUSE_UP,
1303 _zone_gui_frame_mouse_up, zone);
1304
1305 zone->gui.main_box = elm_box_add(zone->gui.frame);
1306 elm_box_horizontal_set(zone->gui.main_box, EINA_FALSE);
1307
1308 zone->gui.create = _zone_gui_button_add
1309 (zone, "add", "Create ruler", _zone_gui_create);
1310 elm_object_disabled_set(zone->gui.create, EINA_TRUE);
1311 zone->gui.clear = _zone_gui_button_add
1312 (zone, "editclear", "Clear rulers", _zone_gui_clear);
1313 elm_object_disabled_set(zone->gui.clear, EINA_TRUE);
1314 _zone_gui_button_add(zone, "keyboard", "Type coordinates", _zone_gui_type);
1315
1316 zone->gui.style = o = elm_hoversel_add(zone->gui.main_box);
1317 elm_hoversel_hover_parent_set(o, zone->win);
1318 _zone_gui_widget_setup(o);
1319 for (i = 0; ruler_type_names_strs[i] != NULL; i++)
1320 {
1321 const char *label = ruler_type_names_strs[i];
1322 elm_hoversel_item_add(o, label, NULL, ELM_ICON_NONE, NULL, NULL);
1323 }
1324 evas_object_smart_callback_add(o, "selected", _zone_gui_style_changed, zone);
1325 _zone_gui_style_label_update(zone);
1326 evas_object_show(o);
1327 elm_box_pack_end(zone->gui.main_box, o);
1328
1329 zone->gui.zoom = _zone_gui_check_add
1330 (zone, !!zone->zoom.image, "Zoom", _zone_gui_zoom_changed);
1331 zone->gui.hex_colors = _zone_gui_check_add
1332 (zone, hex_colors, "Show hexadecimal colors",
1333 _zone_gui_show_hex_colors_changed);
1334 zone->gui.show_guides = _zone_gui_check_add
1335 (zone, show_guides, "Show guidelines", _zone_gui_show_guides_changed);
1336 zone->gui.show_distances = _zone_gui_check_add
1337 (zone, show_distances, "Show distances", _zone_gui_show_distances_changed);
1338
1339 _zone_gui_button_add(zone, "filesaveas", "Save screenshot", _zone_gui_shot);
1340 _zone_gui_button_add(zone, "help", "Help", _zone_gui_help);
1341 _zone_gui_button_add(zone, "exit", "Exit", _zone_gui_exit);
1342
1343 elm_object_content_set(zone->gui.frame, zone->gui.main_box);
1344 evas_object_show(zone->gui.main_box);
1345
1346 evas_object_move(zone->gui.frame, 10, 10);
1347 evas_object_show(zone->gui.frame);
1348}
1349
1350static void
1351zone_zoom_pre_setup(Zone *zone)
1352{
1353 const char *str;
1354
1355 if (zone->zoom.frame) return;
1356
1357 zone->zoom.ideal_size.w = 256;
1358 zone->zoom.ideal_size.h = 256;
1359 zone->zoom.factor = 10;
1360
1361 zone->zoom.frame = edje_object_add(zone->evas);
1362 theme_apply(zone->zoom.frame, "eruler/zoom_viewfinder");
1363
1364 zone->zoom.image = evas_object_image_add(zone->evas);
1365 evas_object_image_smooth_scale_set(zone->zoom.image, EINA_FALSE);
1366 edje_object_part_swallow(zone->zoom.frame, "content", zone->zoom.image);
1367
1368 str = edje_object_data_get(zone->zoom.frame, "ideal_size");
1369 DBG("Zoom viewfinder ideal size: %s", str);
1370 if (str)
1371 {
1372 int n = sscanf(str, "%d %d",
1373 &zone->zoom.ideal_size.w,
1374 &zone->zoom.ideal_size.h);
1375
1376 if (n == 1)
1377 zone->zoom.ideal_size.h = zone->zoom.ideal_size.w;
1378
1379 if (zone->zoom.ideal_size.w < 1)
1380 zone->zoom.ideal_size.w = 256;
1381 if (zone->zoom.ideal_size.h < 1)
1382 zone->zoom.ideal_size.h = 256;
1383 }
1384
1385 str = edje_object_data_get(zone->zoom.frame, "factor");
1386 DBG("Zoom factor: %s", str);
1387 if (str)
1388 {
1389 zone->zoom.factor = atoi(str);
1390 if (zone->zoom.factor < 1)
1391 zone->zoom.factor = 10;
1392 }
1393
1394 zone->zoom.ready = EINA_FALSE;
1395}
1396
1397static void
1398_popup_dismiss_cb(void *data, Evas_Object *o EINA_UNUSED, void *event EINA_UNUSED)
1399{
1400 Evas_Object *popup = data;
1401 evas_object_del(popup);
1402}
1403
1404static void
1405show_gui_help(Zone *zone)
1406{
1407 Evas_Object *popup, *help, *bt;
1408
1409 popup = elm_popup_add(zone->win);
1410 elm_popup_content_text_wrap_type_set(popup, ELM_WRAP_MIXED);
1411
1412 elm_object_part_text_set(popup, "title,text", "ERuler");
1413
1414 help = elm_entry_add(popup);
1415 elm_entry_editable_set(help, EINA_FALSE);
1416 elm_scroller_policy_set(help, ELM_SCROLLER_POLICY_OFF,
1417 ELM_SCROLLER_POLICY_AUTO);
1418
1419 elm_object_text_set
1420 (help,
1421 "Press your mouse's left-button to start measuring, "
1422 "release to stop.<br><br>"
1423 "Keyboard shortcuts:<br>"
1424 " • <b>Escape:</b> quit;<br>"
1425 " • <b>F2:</b> toggle ERuler visibility;<br>"
1426 " • <b>p:</b> print size to stdout;<br>"
1427 " • <b>c:</b> create new ruler;<br>"
1428 " • <b>Control-c:</b> clear current zone rulers;<br>"
1429 " • <b>g:</b> toggle display of guide lines;<br>"
1430 " • <b>d:</b> toggle display of distances between boxes;<br>"
1431 " • <b>t:</b> toggle ruler type (dark, light, filled...);<br>"
1432 " • <b>z:</b> toggle zoom;<br>"
1433 " • <b>x:</b> toggle display of colors in hexadecimal;<br>"
1434 " • <b>@:</b> open command box to type ruler placement;<br>"
1435 " • <b>Space:</b> start or stop measure using keyboard;<br>"
1436 " • <b>Left:</b> move ruler start point to the left (<b>Shift</b> to use 10px step);<br>"
1437 " • <b>Control-Left:</b> move ruler end point to the left (<b>Shift</b> to use 10px step);<br>"
1438 " • <b>Right:</b> move ruler start point to the right (<b>Shift</b> to use 10px step);<br>"
1439 " • <b>Control-Right:</b> move ruler end point to the right (<b>Shift</b> to use 10px step);<br>"
1440 " • <b>Up:</b> move ruler start point up (<b>Shift</b> to use 10px step);<br>"
1441 " • <b>Control-Up:</b> move ruler end point up (<b>Shift</b> to use 10px step);<br>"
1442 " • <b>Down:</b> move ruler start point down (<b>Shift</b> to use 10px step);<br>"
1443 " • <b>Control-Down:</b> move ruler end point down (<b>Shift</b> to use 10px step);<br>"
1444 "");
1445
1446 elm_object_content_set(popup, help);
1447
1448 bt = elm_button_add(popup);
1449 elm_object_text_set(bt, "Dismiss");
1450 evas_object_smart_callback_add(bt, "clicked", _popup_dismiss_cb, popup);
1451 elm_object_part_content_set(popup, "button1", bt);
1452
1453 evas_object_show(popup);
1454 elm_object_focus_set(bt, EINA_TRUE);
1455}
1456
1457static void
1458zone_print_measurements(const Zone *zone)
1459{
1460 const Evas_Object *ruler, *last_ruler;
1461 const Eina_List *l;
1462 unsigned int i;
1463
1464 printf("Zone %d,%d size %dx%d\n", zone->x, zone->y, zone->w, zone->h);
1465 if ((!zone->rulers) ||
1466 ((eina_list_count(zone->rulers) == 1) && (!zone->last_ruler_used)))
1467 {
1468 puts("\tnothing measured.");
1469 return;
1470 }
1471
1472 last_ruler = zone_ruler_last_get(zone);
1473 i = 0;
1474 EINA_LIST_FOREACH(zone->rulers, l, ruler)
1475 {
1476 const Ruler_Data *rd = ruler_data_get(ruler);
1477
1478 if ((ruler == last_ruler) && (!zone->last_ruler_used))
1479 break;
1480
1481 i++;
1482 printf("\tmeasure #%d: %+dx%+d from %d,%d to %d,%d\n",
1483 i,
1484 rd->stop.x - rd->start.x + 1,
1485 rd->stop.y - rd->start.y + 1,
1486 zone->x + rd->start.x,
1487 zone->y + rd->start.y,
1488 zone->x + rd->stop.x,
1489 zone->y + rd->stop.y);
1490 }
1491}
1492
1493static void
1494print_measurements(void)
1495{
1496 const Eina_List *l;
1497 const Zone *zone;
1498 EINA_LIST_FOREACH(zones, l, zone)
1499 zone_print_measurements(zone);
1500}
1501
1502static void
1503_create_ruler_cmdbox_activated(void *data, Evas_Object *o, void *event_info EINA_UNUSED)
1504{
1505 Zone *zone = data;
1506 Evas_Object *ruler;
1507 int x, y, w, h;
1508 const char *str;
1509
1510 str = elm_entry_entry_get(o);
1511 EINA_SAFETY_ON_NULL_GOTO(str, end);
1512
1513 if (sscanf(str, "%d %d %d %d", &x, &y, &w, &h) != 4)
1514 {
1515 ERR("Invalid creation format. Expected 'x y w h', got '%s'", str);
1516 goto end;
1517 }
1518 if (w < 1 || h < 1)
1519 {
1520 ERR("Invalid size: %dx%d", w, h);
1521 goto end;
1522 }
1523
1524 ruler = zone_ruler_last_get(zone);
1525 EINA_SAFETY_ON_NULL_GOTO(ruler, end);
1526
1527 zone_last_ruler_used_set(zone, EINA_TRUE);
1528 ruler_place(ruler, x, y, w, h);
1529
1530 end:
1531 evas_object_del(zone->cmdbox);
1532}
1533
1534static void
1535_create_ruler_cmdbox_aborted(void *data, Evas_Object *o EINA_UNUSED, void *event_info EINA_UNUSED)
1536{
1537 Zone *zone = data;
1538 evas_object_del(zone->cmdbox);
1539}
1540
1541static void
1542_create_ruler_cmdbox_size_changed(void *data, Evas *e EINA_UNUSED, Evas_Object *frame, void *event_info EINA_UNUSED)
1543{
1544 Zone *zone = data;
1545 int mh;
1546
1547 evas_object_size_hint_min_get(frame, NULL, &mh);
1548 evas_object_move(frame, 0, 0);
1549 evas_object_resize(frame, zone->w, mh);
1550}
1551
1552static void
1553_create_ruler_cmdbox_del(void *data, Evas *e EINA_UNUSED, Evas_Object *o EINA_UNUSED, void *event_info EINA_UNUSED)
1554{
1555 Zone *zone = data;
1556 zone->cmdbox = NULL;
1557}
1558
1559static void
1560create_ruler_from_cmdbox(Zone *zone)
1561{
1562 Evas_Object *frame, *entry;
1563
1564 if (zone->cmdbox) return;
1565
1566 frame = elm_frame_add(zone->win);
1567 /* frame has delayed min size calc, listen for size hint changed */
1568 evas_object_event_callback_add(frame, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1569 _create_ruler_cmdbox_size_changed, zone);
1570 evas_object_event_callback_add(frame, EVAS_CALLBACK_DEL,
1571 _create_ruler_cmdbox_del, zone);
1572
1573 if (!zone->last_ruler_used)
1574 elm_object_text_set(frame, "Create ruler (x y w h):");
1575 else
1576 elm_object_text_set(frame, "Edit ruler (x y w h):");
1577
1578 entry = elm_entry_add(frame);
1579 elm_entry_single_line_set(entry, EINA_TRUE);
1580 elm_entry_editable_set(entry, EINA_TRUE);
1581 elm_entry_scrollable_set(entry, EINA_TRUE);
1582 evas_object_show(entry);
1583
1584 evas_object_smart_callback_add(entry, "activated",
1585 _create_ruler_cmdbox_activated, zone);
1586 evas_object_smart_callback_add(entry, "aborted",
1587 _create_ruler_cmdbox_aborted, zone);
1588
1589 elm_object_focus_set(entry, EINA_TRUE);
1590 elm_object_content_set(frame, entry);
1591
1592 evas_object_show(frame);
1593 zone->cmdbox = frame;
1594}
1595
1596static void
1597_create_screenshot_select_done_cb(void *data, Evas_Object *o EINA_UNUSED, void *event)
1598{
1599 Zone *zone = data;
1600 const char *str = event;
1601
1602 if (str)
1603 elm_entry_entry_set(zone->screenshot.file.entry, str);
1604
1605 evas_object_del(zone->screenshot.file.popup);
1606 zone->screenshot.file.popup = NULL;
1607 zone->screenshot.file.selector = NULL;
1608 elm_object_focus_set(zone->screenshot.popup, EINA_TRUE);
1609}
1610
1611static void
1612_create_screenshot_select_cb(void *data, Evas_Object *btn EINA_UNUSED, void *event EINA_UNUSED)
1613{
1614 Zone *zone = data;
1615 Evas_Object *popup, *bx, *sizer, *sel;
1616 const char *fname = elm_entry_entry_get(zone->screenshot.file.entry);
1617
1618 zone->screenshot.file.popup = popup = elm_popup_add(zone->win);
1619 elm_object_part_text_set(popup, "title,text", "Select file to save");
1620
1621 bx = elm_box_add(popup);
1622 elm_box_layout_set(bx, evas_object_box_layout_stack, NULL, NULL);
1623
1624 /* stack + sizer to make popup bigger */
1625 sizer = evas_object_rectangle_add(zone->evas);
1626 evas_object_size_hint_min_set(sizer, zone->w * 0.5, zone->h * 0.5);
1627 evas_object_color_set(sizer, 0, 0, 0, 0);
1628 evas_object_show(sizer);
1629 elm_box_pack_end(bx, sizer);
1630
1631 zone->screenshot.file.selector = sel = elm_fileselector_add(popup);
1632 evas_object_size_hint_weight_set(sel, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1633 evas_object_size_hint_align_set(sel, EVAS_HINT_FILL, EVAS_HINT_FILL);
1634 elm_fileselector_is_save_set(sel, EINA_TRUE);
1635 evas_object_show(sel);
1636
1637 if (fname)
1638 {
1639 if (ecore_file_is_dir(fname))
1640 elm_fileselector_path_set(sel, fname);
1641 else
1642 {
1643 char *dname = ecore_file_dir_get(fname);
1644 elm_fileselector_path_set(sel, dname);
1645 free(dname);
1646 }
1647 }
1648
1649 evas_object_smart_callback_add(sel, "done",
1650 _create_screenshot_select_done_cb, zone);
1651
1652 elm_box_pack_end(bx, sel);
1653 elm_object_content_set(popup, bx);
1654
1655 evas_object_show(popup);
1656}
1657
1658static void
1659_create_screenshot_cleanup(Zone *zone)
1660{
1661 ecore_evas_free(zone->screenshot.ee);
1662 zone->screenshot.ee = NULL;
1663 zone->screenshot.image = NULL;
1664
1665 evas_object_del(zone->screenshot.popup);
1666 zone->screenshot.preview = NULL;
1667 zone->screenshot.popup = NULL;
1668 zone->screenshot.file.entry = NULL;
1669 zone->screenshot.file.button = NULL;
1670 zone->screenshot.file.popup = NULL;
1671 zone->screenshot.file.selector = NULL;
1672
1673 evas_object_focus_set(zone->win, EINA_TRUE);
1674}
1675
1676static void
1677_create_screenshot_notify_dismiss_cb(void *data, Evas_Object *o EINA_UNUSED, void *event EINA_UNUSED)
1678{
1679 evas_object_del(data);
1680}
1681
1682static void
1683_create_screenshot_notify_show(Zone *zone, double timeout, const char *msg)
1684{
1685 Evas_Object *notify, *bx, *o;
1686
1687 notify = elm_notify_add(zone->win);
1688 elm_notify_allow_events_set(notify, EINA_FALSE);
1689 elm_notify_align_set(notify, 0.5, 0.5);
1690 if (timeout > 0.0)
1691 elm_notify_timeout_set(notify, timeout);
1692
1693 bx = elm_box_add(notify);
1694 elm_box_horizontal_set(bx, EINA_FALSE);
1695
1696 o = elm_label_add(bx);
1697 elm_object_text_set(o, msg);
1698 evas_object_show(o);
1699 elm_box_pack_end(bx, o);
1700
1701 o = elm_button_add(bx);
1702 elm_object_text_set(o, "Dismiss");
1703 evas_object_smart_callback_add(o, "clicked",
1704 _create_screenshot_notify_dismiss_cb, notify);
1705 evas_object_show(o);
1706 elm_box_pack_end(bx, o);
1707
1708 evas_object_show(bx);
1709 elm_object_content_set(notify, bx);
1710
1711 evas_object_smart_callback_add(notify, "timeout",
1712 _create_screenshot_notify_dismiss_cb, notify);
1713 evas_object_show(notify);
1714}
1715
1716static Eina_Bool
1717_create_screenshot_save_timer_cb(void *data)
1718{
1719 Zone *zone = data;
1720 const char *fname, *ext, *opts = NULL;
1721 char msg[1024];
1722 char *dname;
1723
1724 fname = elm_object_text_get(zone->screenshot.file.entry);
1725 EINA_SAFETY_ON_NULL_GOTO(fname, error);
1726
1727 dname = ecore_file_dir_get(fname);
1728 if ((dname) && (!ecore_file_is_dir(dname)))
1729 {
1730 if (ecore_file_mkpath(dname))
1731 {
1732 snprintf(msg, sizeof(msg),
1733 "Could not create save directory: \"%s\"", dname);
1734 _create_screenshot_notify_show(zone, -1, msg);
1735 free(dname);
1736 goto error;
1737 }
1738 }
1739 free(dname);
1740
1741 ext = strrchr(fname, '.');
1742 if (ext)
1743 {
1744 ext++;
1745 if (strcasecmp(ext, "png") == 0)
1746 opts = "compress=9";
1747 else if ((strcasecmp(ext, "jpg") == 0) ||
1748 (strcasecmp(ext, "jpeg") == 0))
1749 opts = "quality=95";
1750 }
1751
1752 if (!evas_object_image_save(zone->screenshot.preview, fname, NULL, opts))
1753 {
1754 snprintf(msg, sizeof(msg), "Could not save image: \"%s\"", fname);
1755 _create_screenshot_notify_show(zone, -1, msg);
1756 }
1757 else
1758 {
1759 snprintf(msg, sizeof(msg), "Saved as: \"%s\"", fname);
1760 _create_screenshot_notify_show(zone, 5.0, msg);
1761 }
1762
1763 error:
1764 _create_screenshot_cleanup(zone);
1765 zone->screenshot.timer = NULL;
1766 return EINA_FALSE;
1767}
1768
1769static void
1770_create_screenshot_save_cb(void *data, Evas_Object *o EINA_UNUSED, void *event EINA_UNUSED)
1771{
1772 Zone *zone = data;
1773
1774 elm_object_text_set(zone->screenshot.save_bt, "Wait...");
1775 elm_object_disabled_set(zone->screenshot.save_bt, EINA_TRUE);
1776 elm_object_disabled_set(zone->screenshot.cancel_bt, EINA_TRUE);
1777 elm_object_disabled_set(zone->screenshot.file.entry, EINA_TRUE);
1778 elm_object_disabled_set(zone->screenshot.file.button, EINA_TRUE);
1779
1780 zone->screenshot.timer = ecore_timer_add
1781 (0.01, _create_screenshot_save_timer_cb, zone);
1782}
1783
1784static void
1785_create_screenshot_cancel_cb(void *data, Evas_Object *o EINA_UNUSED, void *event EINA_UNUSED)
1786{
1787 Zone *zone = data;
1788 _create_screenshot_cleanup(zone);
1789}
1790
1791static void
1792find_path_next(char *buf, size_t buflen, const char *dname, const char *fmtname)
1793{
1794 char name[NAME_MAX], *bufp;
1795 size_t bufplen;
1796 unsigned int i;
1797
1798 bufp = buf + eina_strlcpy(buf, dname, buflen);
1799 bufplen = buflen - (bufp - buf);
1800
1801 if ((bufplen > 0) && (bufp[-1] != '/'))
1802 {
1803 bufp[0] = '/';
1804 bufp++;
1805 bufplen--;
1806 }
1807
1808 for (i = 1; i < (unsigned)-1; i++)
1809 {
1810 snprintf(name, sizeof(name), fmtname, i);
1811 eina_strlcpy(bufp, name, bufplen);
1812 if (!ecore_file_exists(buf))
1813 return;
1814 }
1815}
1816
1817static void
1818_create_screenshot_copy_cb(void *data, Eina_Bool success)
1819{
1820 Zone *zone = data;
1821 const Eina_List *l;
1822 const Evas_Object *orig_ruler, *last_ruler;
1823 Evas_Object *popup, *bx, *img, *o, *hbx;
1824 Edje_Message_Int_Set *msg;
1825 Evas *e;
1826 char path[PATH_MAX], buf[128], *bufp;
1827 int iw, ih;
1828 size_t bufplen;
1829 const void *pixels;
1830
1831 if (!success)
1832 {
1833 ecore_evas_free(zone->screenshot.ee);
1834 zone->scre