1 #include "mof/widget/TextCompiler.hpp"
2 #include "mof/widget/WidgetView.hpp"
4 #include <boost/regex.hpp>
6 #include "mof/ConsoleIO.hpp"
7 #include "mof/Sprite.hpp"
8 #include "mof/Font.hpp"
9 #include "mof/widget/Page.hpp"
10 #include "mof/widget/GridLayout.hpp"
11 #include "mof/widget/flow_layout.hpp"
12 #include "mof/widget/Container.hpp"
13 #include "mof/streams.hpp"
14 #include "mof/widget/mofml_parser.hpp"
17 //{{{ PageBehaviorSettings
18 struct PageBehaviorSettings
20 mof::Manipulator<mof::Vector2D>::Handler position;
21 mof::Manipulator<mof::Color4f>::Handler color;
22 mof::FrameNumber periodOfPosition;
23 mof::FrameNumber periodOfColor;
25 std::shared_ptr<PageBehaviorSettings> clone()
27 std::shared_ptr<PageBehaviorSettings> p = std::make_shared<PageBehaviorSettings>();
28 p->periodOfPosition = periodOfPosition;
29 p->periodOfColor = periodOfColor;
30 p->position = position;
36 class SpriteWidgetViewAdapter : public mof::widget::WidgetView
38 std::unique_ptr<mof::Sprite> pSprite_;
39 mof::Vector2D preferredSize_;
40 std::shared_ptr<const PageBehaviorSettings> openSettings_;
41 std::shared_ptr<const PageBehaviorSettings> closeSettings_;
42 mof::ReferenceWrapper<mof::Vector2D> positionWrapper_;
43 mof::ReferenceWrapper<mof::Color4f> colorWrapper_;
46 SpriteWidgetViewAdapter
48 std::unique_ptr<mof::Sprite>&& pSprite,
49 std::shared_ptr<const PageBehaviorSettings> openSettings,
50 std::shared_ptr<const PageBehaviorSettings> closeSettings
52 : pSprite_(std::move(pSprite)), openSettings_(openSettings), closeSettings_(closeSettings)
54 pSprite_->setVisible(true);
55 pSprite_->getPositionStream() << m_positionStream << positionWrapper_.makeRef(mof::Vector2D(0, 0));
56 pSprite_->getColorStream() << m_colorStream << colorWrapper_.makeRef(mof::Color4f(0, 1, 1, 1));
57 preferredSize_ = pSprite_->getSizeStream().value();
58 m_sizeStream << preferredSize_;
62 virtual ~SpriteWidgetViewAdapter(){}
65 virtual mof::FrameNumber show(bool immidiately)
68 positionWrapper_.replace(openSettings_->periodOfPosition, openSettings_->position);
69 colorWrapper_.replace(openSettings_->periodOfColor, openSettings_->color);
72 positionWrapper_.replace(0, getPositionStream(), openSettings_->position);
73 colorWrapper_.replace(0, getColorStream(), openSettings_->color);
74 return max(openSettings_->periodOfPosition, openSettings_->periodOfColor);
78 virtual mof::FrameNumber hide(bool immidiately)
81 positionWrapper_.replace(closeSettings_->periodOfPosition, closeSettings_->position);
82 colorWrapper_.replace(closeSettings_->periodOfColor, closeSettings_->color);
85 positionWrapper_.replace(0, getPositionStream(), closeSettings_->position);
86 colorWrapper_.replace(0, getColorStream(), closeSettings_->color);
87 return max(closeSettings_->periodOfPosition, closeSettings_->periodOfColor);
91 virtual mof::FrameNumber focus(bool immidiately){ return show(immidiately); }
94 virtual mof::FrameNumber blur(bool immidiately){ return hide(immidiately); }
97 virtual mof::FrameNumber click(bool){return 0;}
99 //{{{ getPreferredSize
100 virtual mof::Vector2D getPreferredSize() const { return preferredSize_; }
105 m_positionStream.update();
106 m_sizeStream.update();
107 m_colorStream.update();
108 pSprite_->getPositionStream().update();
109 pSprite_->getSizeStream().update();
110 pSprite_->getColorStream().update();
111 pSprite_->getRectangleCoordinatesStream().update();
115 void draw() const { pSprite_->draw(); }
118 void setVisible(bool visible) { pSprite_->setVisible(visible); }
130 struct TextCompiler::Impl
133 std::shared_ptr<PageBehaviorSettings> openSettings_;
134 std::shared_ptr<PageBehaviorSettings> closeSettings_;
135 boost::function<mof::Texture::ptr (const mof::tstring&)> texture_factory_;
136 mof::widget::mofml_parser parser;
138 Impl(const mof::Font& font)
141 openSettings_ = std::make_shared<PageBehaviorSettings>();
142 closeSettings_ = std::make_shared<PageBehaviorSettings>();
144 openSettings_->position = closeSettings_->position = mof::makeConstantHandler(mof::Vector2D(0, 0));
145 openSettings_->color = mof::makeConstantHandler(mof::Color4f(1, 1, 1, 1));
146 closeSettings_->color = mof::makeConstantHandler(mof::Color4f(0, 1, 1, 1));
147 openSettings_->periodOfPosition = openSettings_->periodOfColor = 0;
148 closeSettings_->periodOfPosition = closeSettings_->periodOfColor = 0;
151 //{{{ make_line_widget_
152 mof::widget::WidgetView::ptr make_line_widget_(const std::vector<mof::widget::WidgetView::ptr>& widgets_on_a_line)
154 if (widgets_on_a_line.size() == 1) {
155 return widgets_on_a_line.front();
158 WidgetView::ptr p = std::make_shared<Container>
160 widgets_on_a_line.front(), widgets_on_a_line.back() ,
161 mof::makeFactoryMethod<GridLayout>(GridLayout::HORIZONTAL , 0 )
167 //{{{ make_layout_widget_
168 mof::widget::WidgetView::ptr make_layout_widget_
170 const std::vector<mof::widget::WidgetView::ptr>& widgets_in_layout,
171 const mof::widget::mofml_parser::layout_end_node& layout_node
174 using namespace mof::widget;
176 flow_layout::xalign xa = layout_node.xalign;
177 flow_layout::yalign ya = layout_node.yalign;
178 size_t width = layout_node.width;
179 size_t height = layout_node.height;
180 WidgetView::ptr p = std::make_shared<Container>
182 widgets_in_layout.front(), widgets_in_layout.back() ,
183 mof::makeFactoryMethod<flow_layout>(xa, ya, width, height)
189 void recursive // TODO 改名
191 const mof::tstring& text,
192 std::vector<mof::widget::WidgetView::ptr>& result,
193 const mof::Font& font
197 using namespace mof::widget;
199 parser.set_text(text);
200 mof::font_context context;
201 std::vector<std::vector<mof::widget::WidgetView::ptr>> layout_widgets(1);
203 while (parser.has_next_node()) {
204 mofml_parser::node node = parser.next_node();
205 // ノードの内容を解釈してコンテキストに変換
206 if (node.which() == mofml_parser::TEXT) {
207 auto& text_node = boost::get<mofml_parser::text_node>(node);
208 context.font_color = text_node.font_color;
209 std::unique_ptr<mof::Sprite> pSprite
211 mof::Sprite::createTextSprite(mof::Font(font.name().c_str(), font.size(), context), text_node.text)
213 auto p = std::make_shared<SpriteWidgetViewAdapter>(std::move(pSprite), openSettings_, closeSettings_);
214 layout_widgets.back().push_back(p);// 新しいノードを積む
216 else if (node.which() == mofml_parser::IMAGE) {
217 auto& image_node = boost::get<mofml_parser::image_node>(node);
218 std::unique_ptr<mof::Sprite> pSprite
222 Rectangle<int>(0, 0, image_node.width, image_node.height),
223 texture_factory_(image_node.src),
227 auto p = std::make_shared<SpriteWidgetViewAdapter>(std::move(pSprite), openSettings_, closeSettings_);
228 layout_widgets.back().push_back(p);// 新しいノードを積む
230 else if (node.which() == mofml_parser::NEW_LINE || node.which() == mofml_parser::END) {
231 if (!layout_widgets[0].empty()) {
232 // 1行分のウィジェットをまとめて、横方向に配置
233 result.push_back(make_line_widget_(layout_widgets[0]));
234 layout_widgets[0].clear();
237 else if (node.which() == mofml_parser::LAYOUT_START) {
238 layout_widgets.push_back(std::vector<mof::widget::WidgetView::ptr>());
240 else if (node.which() == mofml_parser::LAYOUT_END) {
241 auto& layout_node = boost::get<mofml_parser::layout_end_node>(node);
242 auto& widgets = layout_widgets.back();
243 if (!widgets.empty()) (++layout_widgets.rbegin())->push_back(make_layout_widget_(widgets, layout_node));
244 layout_widgets.pop_back();
254 TextCompiler::TextCompiler(const mof::Font& font)
255 : pImpl_(new Impl(font))
257 pImpl_->texture_factory_ = [](const mof::tstring& path){ return std::make_shared<mof::Texture>(path); };
261 TextCompiler::TextCompiler(const mof::Font& font, const boost::function<mof::Texture::ptr (const mof::tstring&)>& factory)
262 : pImpl_(new Impl(font))
264 pImpl_->texture_factory_ = factory;
268 TextCompiler::~TextCompiler()
272 //{{{ set_texture_factory
273 void TextCompiler::set_texture_factory
275 const boost::function<mof::Texture::ptr (const mof::tstring&)>& factory
278 pImpl_->texture_factory_ = factory;
282 std::auto_ptr<mof::widget::Page> TextCompiler::compile(const mof::tstring& text)
284 using namespace mof::widget;
285 using namespace boost;
287 using mof::widget::GridLayout;
289 std::vector< std::shared_ptr<WidgetView> > result;
290 pImpl_->recursive(text, result, pImpl_->font_);
293 return std::auto_ptr<Page>
297 std::make_shared<Container>
299 result.front(), result.back() ,
300 mof::makeFactoryMethod<GridLayout>(GridLayout::VERTICAL , 0 )
302 _T("not implemented")
308 std::auto_ptr<mof::widget::WidgetView> TextCompiler::compile_d(const mof::tstring& text)
310 using namespace mof::widget;
311 using namespace boost;
313 using mof::widget::GridLayout;
315 std::vector<WidgetView::ptr> result;
316 pImpl_->recursive(text, result, pImpl_->font_);
318 return std::auto_ptr<WidgetView>
322 result.front(), result.back() ,
323 mof::makeFactoryMethod<GridLayout>(GridLayout::VERTICAL , 0 )
328 //{{{ setBehaviorOnPosition
329 void TextCompiler::setBehaviorOnPosition
331 BehaviorTarget target,
332 mof::Manipulator<mof::Vector2D>::Handler position,
337 case TextCompiler::PAGE_OPEN :
339 std::shared_ptr<PageBehaviorSettings> p = pImpl_->openSettings_;
340 p->position = position;
341 p->periodOfPosition = period;
342 pImpl_->openSettings_ = p;
345 case TextCompiler::PAGE_CLOSE :
347 std::shared_ptr<PageBehaviorSettings> p = pImpl_->closeSettings_;
348 p->position = position;
349 p->periodOfPosition = period;
350 pImpl_->closeSettings_ = p;
357 //{{{ setBehaviorOnColor
358 void TextCompiler::setBehaviorOnColor
360 BehaviorTarget target,
361 mof::Manipulator<mof::Color4f>::Handler color,
366 case TextCompiler::PAGE_OPEN :
368 std::shared_ptr<PageBehaviorSettings> p = pImpl_->openSettings_;
370 p->periodOfColor = period;
371 pImpl_->openSettings_ = p;
374 case TextCompiler::PAGE_CLOSE :
376 std::shared_ptr<PageBehaviorSettings> p = pImpl_->closeSettings_;
378 p->periodOfColor = period;
379 pImpl_->closeSettings_ = p;