Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
 
3
class FeatureToc {
4
  var $_anchor_locator;
5
  var $_document_updater;
6
 
7
  function FeatureToc() {
8
    $this->set_anchor_locator(new FeatureTocAnchorLocatorHeaders());
9
    $this->set_document_updater(new FeatureTocDocumentUpdaterPrependPage());
10
  }
11
 
12
  function handle_after_parse($params) {
13
    $pipeline =& $params['pipeline'];
14
    $document =& $params['document'];
15
    $media =& $params['media'];
16
 
17
    $toc =& $this->find_toc_anchors($pipeline, $media, $document);
18
    $this->update_document($toc, $pipeline, $media, $document);
19
  }
20
 
21
  function handle_before_document($params) {
22
    $pipeline =& $params['pipeline'];
23
    $document =& $params['document'];
24
    $media =& $params['media'];
25
    $page_heights =& $params['page-heights'];
26
 
27
    $toc =& $this->find_toc_anchors($pipeline, $media, $document);
28
    $this->update_page_numbers($toc, $pipeline, $document, $page_heights, $media);
29
  }
30
 
31
  function &find_toc_anchors(&$pipeline, &$media, &$document) {
32
    $locator =& $this->get_anchor_locator();
33
    $toc =& $locator->run($pipeline, $media, $document);
34
    return $toc;
35
  }
36
 
37
  function &get_anchor_locator() {
38
    return $this->_anchor_locator;
39
  }
40
 
41
  function &get_document_updater() {
42
    return $this->_document_updater;
43
  }
44
 
45
  function guess_page(&$element, $page_heights, &$media) {
46
    $page_index = 0;
47
    $bottom = mm2pt($media->height() - $media->margins['top']);
48
    do {
49
      $bottom -= $page_heights[$page_index];
50
      $page_index ++;
51
    } while ($element->get_top() < $bottom);
52
 
53
    return $page_index;
54
  }
55
 
56
  function install(&$pipeline, $params) {
57
    $dispatcher =& $pipeline->get_dispatcher();
58
    $dispatcher->add_observer('after-parse', array(&$this, 'handle_after_parse'));
59
    $dispatcher->add_observer('before-document', array(&$this, 'handle_before_document'));
60
 
61
    if (isset($params['location'])) {
62
      switch ($params['location']) {
63
      case 'placeholder':
64
        $this->set_document_updater(new FeatureTocDocumentUpdaterPlaceholder());
65
        break;
66
      case 'before':
67
        $this->set_document_updater(new FeatureTocDocumentUpdaterPrependPage());
68
        break;
69
      case 'after':
70
      default:
71
        $this->set_document_updater(new FeatureTocDocumentUpdaterAppendPage());
72
        break;
73
      };
74
    };
75
  }
76
 
77
  function set_anchor_locator(&$locator) {
78
    $this->_anchor_locator =& $locator;
79
  }
80
 
81
  function set_document_updater(&$updater) {
82
    $this->_document_updater =& $updater;
83
  }
84
 
85
  function make_toc_name_element_id($index) {
86
    return sprintf('html2ps-toc-name-%d', $index);
87
  }
88
 
89
  function make_toc_page_element_id($index) {
90
    return sprintf('html2ps-toc-page-%d', $index);
91
  }
92
 
93
  function update_document(&$toc, &$pipeline, &$media, &$document) {
94
    $code = '';
95
    $index = 1;
96
    foreach ($toc as $toc_element) {
97
      $code .= sprintf('
98
<div id="html2ps-toc-%s" class="html2ps-toc-wrapper html2ps-toc-%d-wrapper">
99
<div id="%s" class="html2ps-toc-name html2ps-toc-%d-name"><a href="#%s">%s</a></div>
100
<div id="%s" class="html2ps-toc-page html2ps-toc-%d-page">0000</div>
101
</div>%s',
102
                       $index,
103
                       $toc_element['level'],
104
                       $this->make_toc_name_element_id($index),
105
                       $toc_element['level'],
106
                       $toc_element['anchor'],
107
                       $toc_element['name'],
108
                       $this->make_toc_page_element_id($index),
109
                       $toc_element['level'],
110
                       "\n");
111
      $index++;
112
    };
113
 
114
    $toc_box_document =& $pipeline->parser->process('<body><div>'.$code.'</div></body>', $pipeline, $media);
115
    $context =& new FlowContext();
116
    $pipeline->layout_engine->process($toc_box_document, $media, $pipeline->get_output_driver(), $context);
117
    $toc_box =& $toc_box_document->content[0];
118
 
119
    $document_updater =& $this->get_document_updater();
120
    $document_updater->run($toc_box, $media, $document);
121
  }
122
 
123
  function update_page_numbers(&$toc, &$pipeline, &$document, &$page_heights, &$media) {
124
    for ($i = 0, $size = count($toc); $i < $size; $i++) {
125
      $toc_element =& $document->get_element_by_id($this->make_toc_page_element_id($i+1));
126
      $element =& $toc[$i]['element'];
127
 
128
      $toc_element->content[0]->content[0]->words[0] = $this->guess_page($element, $page_heights, $media);
129
    };
130
  }
131
}
132
 
133
class FeatureTocAnchorLocatorHeaders {
134
  var $_locations;
135
  var $_last_generated_anchor_id;
136
 
137
  function FeatureTocAnchorLocatorHeaders() {
138
    $this->set_locations(array());
139
    $this->_last_generated_anchor_id = 0;
140
  }
141
 
142
  function generate_toc_anchor_id() {
143
    $this->_last_generated_anchor_id++;
144
    $id = $this->_last_generated_anchor_id;
145
    return sprintf('html2ps-toc-element-%d', $id);
146
  }
147
 
148
  function get_locations() {
149
    return $this->_locations;
150
  }
151
 
152
  function process_node($params) {
153
    $node =& $params['node'];
154
 
155
    if (preg_match('/^h(\d)$/i', $node->get_tagname(), $matches)) {
156
      if (!$node->get_id()) {
157
        $id = $this->generate_toc_anchor_id();
158
        $node->set_id($id);
159
      };
160
 
161
      $this->_locations[] = array('name' => $node->get_content(),
162
                                  'level' => (int)$matches[1],
163
                                  'anchor' => $node->get_id(),
164
                                  'element' => &$node);
165
    };
166
  }
167
 
168
  function &run(&$pipeline, &$media, &$document) {
169
    $this->set_locations(array());
170
    $walker =& new TreeWalkerDepthFirst(array(&$this, 'process_node'));
171
    $walker->run($document);
172
    $locations = $this->get_locations();
173
 
174
    foreach ($locations as $location) {
175
      $location['element']->setCSSProperty(CSS_HTML2PS_LINK_DESTINATION, $location['element']->get_id());
176
 
177
      // $id = $location['element']->get_id();
178
      // $pipeline->output_driver->anchors[$id] =& $location['element']->make_anchor($media, $id);
179
    };
180
 
181
    return $locations;
182
  }
183
 
184
  function set_locations($locations) {
185
    $this->_locations = $locations;
186
  }
187
}
188
 
189
class FeatureTocDocumentUpdaterAppendPage {
190
  function FeatureTocDocumentUpdaterAppendPage() {
191
  }
192
 
193
  function run(&$toc_box, &$media, &$document) {
194
    $toc_box->setCSSProperty(CSS_PAGE_BREAK_BEFORE, PAGE_BREAK_ALWAYS);
195
    $document->append_child($toc_box);
196
  }
197
}
198
 
199
class FeatureTocDocumentUpdaterPrependPage {
200
  function FeatureTocDocumentUpdaterPrependPage() {
201
  }
202
 
203
  function run(&$toc_box, &$media, &$document) {
204
    $toc_box->setCSSProperty(CSS_PAGE_BREAK_AFTER, PAGE_BREAK_ALWAYS);
205
    $document->insert_before($toc_box, $document->content[0]);
206
  }
207
}
208
 
209
class FeatureTocDocumentUpdaterPlaceholder {
210
  function FeatureTocDocumentUpdaterPlaceholder() {
211
  }
212
 
213
  function run(&$toc_box, &$media, &$document) {
214
    $placeholder =& $document->get_element_by_id('html2ps-toc');
215
    $placeholder->append_child($toc_box);
216
  }
217
}
218
 
219
?>