From mboxrd@z Thu Jan 1 00:00:00 1970 From: julia.jacobson@arcor.de Subject: Review of code adding grouping feature to Gantt chart creation Date: Wed, 13 Jun 2012 17:19:42 +0200 (CEST) Message-ID: <972094749.25814.1339600782029.JavaMail.ngmail@webmail09.arcor-online.net> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_Part_25812_439043223.1339600782027" Return-path: Received: from eggs.gnu.org ([208.118.235.92]:37359) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SepMJ-0003b3-7Y for emacs-orgmode@gnu.org; Wed, 13 Jun 2012 11:19:48 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SepMH-0000vL-3o for emacs-orgmode@gnu.org; Wed, 13 Jun 2012 11:19:46 -0400 Received: from mail-in-14.arcor-online.net ([151.189.21.54]:35703) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SepMG-0000uY-GJ for emacs-orgmode@gnu.org; Wed, 13 Jun 2012 11:19:45 -0400 Received: from mail-in-10-z2.arcor-online.net (mail-in-10-z2.arcor-online.net [151.189.8.27]) by mx.arcor.de (Postfix) with ESMTP id 1F6EB173C38 for ; Wed, 13 Jun 2012 17:19:42 +0200 (CEST) Received: from mail-in-04.arcor-online.net (mail-in-04.arcor-online.net [151.189.21.44]) by mail-in-10-z2.arcor-online.net (Postfix) with ESMTP id 05B842EF for ; Wed, 13 Jun 2012 17:19:42 +0200 (CEST) Received: from webmail09.arcor-online.net (webmail09.arcor-online.net [151.189.8.45]) by mail-in-04.arcor-online.net (Postfix) with ESMTP id F082DAA081 for ; Wed, 13 Jun 2012 17:19:41 +0200 (CEST) List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: emacs-orgmode@gnu.org ------=_Part_25812_439043223.1339600782027 Content-Type: multipart/alternative; boundary="----=_Part_25811_186574949.1339600782026" ------=_Part_25811_186574949.1339600782026 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Dear Orgmode Community, Some time ago, Eric Fraga wrote a lisp function and some LaTeX code to generate Gantt charts from within orgmode and posted it to this mailing list. This code proved to be very helpful to me and therefore I added a feature for indicating the progress of a task, which has also been posted to this list. Some project management tools like Microsoft Project or Taskjuggler allow to visually summarize neighboring tasks in a group by aligning them under a limiting bar. I tried to implement this feature in Eric Fraga's code, too, and hope that some of you might find it helpful. Moreover, the attachment of this post contains an improvement of the progress bar feature, which I added previously. Please don't hesitate to write me if you discover a bug in my code or have any ideas for improvement. Maybe someone is even willing to add it to org-mode's the library of babel. Finally, I would like to put up for discussion, whether it makes to add new features for generating Gantt charts like this. After all, there is already the possibility to create very elaborate Gantt charts from an orgmode file by exporting to taskjuggler. Furthermore, there's a LaTeX package called pgfgantt, which simplifies the creation of Gantt charts. The advantage of the lisp and LaTeX code is that it doesn't create any additional dependencies (well, maybe except for TikZ which ships with current TeX distributions). The best architectural solution might be to write a Orgmode interface for the pgfgantt LaTeX package. Kind regards, Julia ------=_Part_25811_186574949.1339600782026-- ------=_Part_25812_439043223.1339600782027 Content-Type: application/octet-stream Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=group_prog.org #+TITLE: Gantt charts with feature for grouping #+AUTHOR: Julia Jacobson #+EMAIL: julia.jacobson@arcor.de #+DATE: \today #+LASTCHANGE: 2012.06.13 15:30:00 #+DESCRIPTION: #+KEYWORDS: #+LANGUAGE: en #+OPTIONS: H:3 num:nil toc:nil \n:nil @:t ::t |:t ^:t -:t f:t *:t <:t #+OPTIONS: TeX:t LaTeX:t skip:nil d:nil todo:t pri:nil tags:not-in-toc #+INFOJS_OPT: view:nil toc:nil ltoc:t mouse:underline buttons:0 path:http://orgmode.org/org-info.js #+EXPORT_SELECT_TAGS: export #+EXPORT_EXCLUDE_TAGS: noexport #+LINK_UP: #+LINK_HOME: #+latex_header: \usepackage{pgf, pgfarrows, pgfnodes} #+latex_header: \usepackage{tikz} #+latex_header: \newcommand\ganttline[4]{% line, tag, start end #+latex_header: \node at (0,#1) [anchor=base east] {#2}; #+latex_header: \fill[black!20!white] (#3/20,#1-.2) rectangle (#4/20,#1+.2);} * Table of tasks and milestones :noexport: An additional type ''group'' for grouping tasks is added. #+tblname: gantttesttable | | type | label | activity | depends | start | duration | end | align | progress | |----+-----------+---------+--------------------+---------+-------+----------+-----+-------+----------| | 1 | date | Start | | | 0 | | 0 | | | | 4 | group | | Practical Work | | 0 | 14 | 14 | | | | 2 | task | 1.1 | Lit survey | | 0 | 2 | 2 | right | 75 | | 3 | task | 1.2 | Measurements | | 2 | 6 | 8 | | 40 | | 4 | milestone | M1 | data collected | 3 | 8 | | 8 | | | | 5 | task | 1.3 | Report | 3 | 8 | 6 | 14 | | 30 | | 6 | date | 14 days | | | 14 | | 14 | | | | 7 | milestone | M2 | Release | 5 | 14 | | 14 | | | |----+-----------+---------+--------------------+---------+-------+----------+-----+-------+----------| | 4 | group | | Post-release tasks | | 14 | 2 | 16 | left | | | 8 | task | 2.1 | Discuss | 5 | 14 | 1 | 15 | left | 90 | | 9 | task | 2.2 | Correct mistakes | 8 | 15 | 1 | 16 | left | 10 | | 10 | task | 2.3 | Add feedback | 5 | 14 | 2 | 16 | left | 50 | | 11 | date | End | | | 16 | | 16 | | | |----+-----------+---------+--------------------+---------+-------+----------+-----+-------+----------| #+TBLFM: address@hidden::$8=$6+$7::@address@hidden::@address@hidden::@address@hidden::@address@hidden::@address@hidden * lisp code for creating latex that uses above :noexport: #+name: elispgantt #+begin_src emacs-lisp :var table=gantttesttable :results raw :export results (defun esf/generate-gantt-chart (table) (let ((dates "") (entries (nthcdr 2 table)) (milestones "") (nmilestones 0) (ntasks 0) (projecttime 0) (tasks "") (xlength 1) (progress 1) ) (message "Initial: %s\n" table) (message "Entries: %s\n" entries) (while entries (let ((entry (first entries))) (if (listp entry) (let ((id (first entry)) (type (nth 1 entry)) (label (nth 2 entry)) (task (nth 3 entry)) (dependencies (nth 4 entry)) (start (nth 5 entry)) (duration (nth 6 entry)) (end (nth 7 entry)) (alignment (nth 8 entry)) (progress (nth 9 entry)) ) (if (> start projecttime) (setq projecttime start)) (if (string= type "task") (let ((end (+ start duration)) (textposition (+ start (/ duration 2))) (flush "") ) (if (string= alignment "left") (progn (setq textposition start) (setq flush "[left]")) (if (string= alignment "right") (progn (setq textposition end) (setq flush "[right]")) ) ) (setq tasks (format "%s \\gantttask{%s}{%s}{%d}{%d}{%d}{%s}{%d}\n" tasks label task start end textposition flush progress)) (setq ntasks (+ 1 ntasks)) (if (> end projecttime) (setq projecttime end)) ) (if (string= type "group") (let ((end (+ start duration)) (textposition (+ start (/ duration 2))) (flush "") ) (if (string= alignment "left") (progn (setq textposition start) (setq flush "[left]")) (if (string= alignment "right") (progn (setq textposition end) (setq flush "[right]")) ) ) (setq tasks (format "%s \\ganttgroup{%s}{%s}{%d}{%d}{%d}{%s}\n" tasks label task start end textposition flush)) (setq ntasks (+ 1 ntasks)) (if (> end projecttime) (setq projecttime end)) ) ) (if (string= type "milestone") (progn (setq milestones (format "%s \\ganttmilestone{$\\begin{array}{c}\\mbox{%s}\\\\ \\mbox{%s}\\end{array}$}{%d}\n" milestones label task start)) (setq nmilestones (+ 1 nmilestones))) (if (string= type "date") (setq dates (format "%s \\ganttdateline{%s}{%d}\n" dates label start)) (message "Ignoring entry with type %s\n" type) ) ) ) ) (message "Ignoring non-list entry %s\n" entry) ) ; end if list entry (setq entries (cdr entries)) ) ) ; end while entries left (format "#+begin_latex \\pgfdeclarelayer{background} \\pgfdeclarelayer{foreground} \\pgfsetlayers{background,foreground} \\renewcommand{\\ganttprojecttime}{%d} \\renewcommand{\\ganttntasks}{%d} \\noindent \\begin{tikzpicture}[y=-0.75cm,x=0.75\\textwidth] \\begin{pgfonlayer}{background} \\draw[very thin, red!10!white] (0,1+\\ganttntasks) grid [ystep=0.75cm,xstep=1/\\ganttprojecttime] (1,0); \\draw[\\ganttdatelinecolour] (0,0) -- (1,0); \\draw[\\ganttdatelinecolour] (0,1+\\ganttntasks) -- (1,1+\\ganttntasks); \\end{pgfonlayer} %s %s %s \\end{tikzpicture} ,#+end_latex\n" projecttime ntasks tasks milestones dates) ) ) (esf/generate-gantt-chart table) #+end_src * Time line #+latex_header: \usepackage{tikz} #+begin_latex \newcounter{gantttask} \newcommand{\ganttprogresscolour}{green!75!white} \newcommand{\ganttremainingcolour}{red!75!white} \newcommand{\ganttmilestonecolour}{red!50!white} \newcommand{\ganttdatelinecolour}{black!50!white} \newcommand{\ganttprojecttime}{1} \newcommand{\ganttntasks}{1} \newcommand\gantttask[7]{% label, activity, start, end, labelpos, align, progress \begin{pgfonlayer}{foreground} \stepcounter{gantttask} \node [left] at (0,\thegantttask) {#1}; \draw[fill=\ganttremainingcolour,draw=no] (#3/\ganttprojecttime,\thegantttask-0.4) rectangle (#4/\ganttprojecttime,\thegantttask + 0.4); \draw[fill=\ganttprogresscolour,draw=no] (#3/\ganttprojecttime,\thegantttask-0.3) rectangle (#3/\ganttprojecttime + #7/100 * #4/\ganttprojecttime - #7/100 * #3/\ganttprojecttime,\thegantttask + 0.3); \node at (#5/\ganttprojecttime,\thegantttask) #6 {#2}; \end{pgfonlayer} } \newcommand\ganttgroup[6]{% label, activity, start, end, labelpos, align \begin{pgfonlayer}{foreground} \stepcounter{gantttask} \node [left] at (0,\thegantttask) {#1}; \fill[blue] (#3/\ganttprojecttime-0.1/\ganttprojecttime,\thegantttask-0.3) rectangle (#4/\ganttprojecttime+0.1/\ganttprojecttime,\thegantttask +0.3); \fill[blue] (#3/\ganttprojecttime-0.1/\ganttprojecttime,\thegantttask+0.3) -- (#3/\ganttprojecttime,\thegantttask+0.4) -- (#3/\ganttprojecttime+0.1/\ganttprojecttime,\thegantttask+0.3) -- cycle; \fill[blue] (#4/\ganttprojecttime+0.1/\ganttprojecttime,\thegantttask+0.3) -- (#4/\ganttprojecttime,\thegantttask+0.4) -- (#4/\ganttprojecttime-0.1/\ganttprojecttime,\thegantttask+0.3) -- cycle; \node at (#5/\ganttprojecttime,\thegantttask) [text=black] #6 {#2}; \end{pgfonlayer} } \newcommand\ganttpoint[3]{% line, tag, date \node at (0,#1) [anchor=base east] {#2}; \fill[black] (#3/\ganttprojecttime,#1) circle (0.1/\ganttprojecttime); } \newcommand\ganttdateline[2]{% tag, date \begin{pgfonlayer}{background} \draw[\ganttdatelinecolour] (#2/\ganttprojecttime,0) -- (#2/\ganttprojecttime,\thegantttask+1); \node at (#2/\ganttprojecttime,0) [above] {#1}; \end{pgfonlayer} } \newcommand\ganttmilestone[2]{% tag, date \begin{pgfonlayer}{foreground} \node at (#2/\ganttprojecttime,\thegantttask+1.0) [below] {#1}; \draw[black,fill=\ganttmilestonecolour] (#2/\ganttprojecttime-0.1\ganttntasks/\ganttprojecttime,\thegantttask+0.9) rectangle (#2/\ganttprojecttime+0.1\ganttntasks/\ganttprojecttime,\thegantttask+1.1); \end{pgfonlayer} } #+END_LaTeX #+RESULTS: elispgantt #+begin_latex \pgfdeclarelayer{background} \pgfdeclarelayer{foreground} \pgfsetlayers{background,foreground} \renewcommand{\ganttprojecttime}{16} \renewcommand{\ganttntasks}{8} \noindent \begin{tikzpicture}[y=-0.75cm,x=0.75\textwidth] \begin{pgfonlayer}{background} \draw[very thin, red!10!white] (0,1+\ganttntasks) grid [ystep=0.75cm,xstep=1/\ganttprojecttime] (1,0); \draw[\ganttdatelinecolour] (0,0) -- (1,0); \draw[\ganttdatelinecolour] (0,1+\ganttntasks) -- (1,1+\ganttntasks); \end{pgfonlayer} \ganttgroup{}{Practical Work}{0}{14}{7}{} \gantttask{1.1}{Lit survey}{0}{2}{2}{[right]}{75} \gantttask{1.2}{Measurements}{2}{8}{5}{}{40} \gantttask{1.3}{Report}{8}{14}{11}{}{30} \ganttgroup{}{Post-release tasks}{14}{16}{14}{[left]} \gantttask{2.1}{Discuss}{14}{15}{14}{[left]}{90} \gantttask{2.2}{Correct mistakes}{15}{16}{15}{[left]}{10} \gantttask{2.3}{Add feedback}{14}{16}{14}{[left]}{50} \ganttmilestone{$\begin{array}{c}\mbox{M1}\\ \mbox{data collected}\end{array}$}{8} \ganttmilestone{$\begin{array}{c}\mbox{M2}\\ \mbox{Release}\end{array}$}{14} \ganttdateline{Start}{0} \ganttdateline{14 days}{14} \ganttdateline{End}{16} \end{tikzpicture} #+end_latex #+ \\draw[help lines, very thin, red!20!white] (0,%s) grid (\\ganttprojecttime,0); # <> ------=_Part_25812_439043223.1339600782027--