Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "CellBorderStyleControl.hxx"
21 : #include "sc.hrc"
22 : #include "scresid.hxx"
23 : #include <CellAppearancePropertyPanel.hrc>
24 : #include <editeng/boxitem.hxx>
25 : #include <editeng/borderline.hxx>
26 : #include "CellAppearancePropertyPanel.hxx"
27 : #include <sfx2/bindings.hxx>
28 : #include <sfx2/dispatch.hxx>
29 : #include <vcl/svapp.hxx>
30 : #include <vcl/settings.hxx>
31 : #include <editeng/lineitem.hxx>
32 : #include <boost/scoped_ptr.hpp>
33 :
34 : namespace sc { namespace sidebar {
35 :
36 : #define FRM_VALID_LEFT 0x01
37 : #define FRM_VALID_RIGHT 0x02
38 : #define FRM_VALID_TOP 0x04
39 : #define FRM_VALID_BOTTOM 0x08
40 : #define FRM_VALID_HINNER 0x10
41 : #define FRM_VALID_VINNER 0x20
42 : #define FRM_VALID_OUTER 0x0f
43 : #define FRM_VALID_ALL 0xff
44 :
45 0 : CellBorderStyleControl::CellBorderStyleControl(vcl::Window* pParent, CellAppearancePropertyPanel& rPanel)
46 : : svx::sidebar::PopupControl(pParent, ScResId(RID_POPUPPANEL_APPEARANCE_CELL_BORDERSTYLE)),
47 : mrCellAppearancePropertyPanel(rPanel),
48 : maTBBorder1(VclPtr<ToolBox>::Create(this, ScResId(TB_BORDER1))),
49 : maTBBorder2(VclPtr<ToolBox>::Create(this, ScResId(TB_BORDER2))),
50 : maTBBorder3(VclPtr<ToolBox>::Create(this, ScResId(TB_BORDER3))),
51 : maFL1(VclPtr<FixedLine>::Create(this, ScResId(FL_1))),
52 : maFL2(VclPtr<FixedLine>::Create(this, ScResId(FL_2))),
53 0 : mpImageList(0)
54 : {
55 0 : Initialize();
56 0 : FreeResource();
57 0 : }
58 :
59 0 : CellBorderStyleControl::~CellBorderStyleControl()
60 : {
61 0 : disposeOnce();
62 0 : }
63 :
64 0 : void CellBorderStyleControl::dispose()
65 : {
66 0 : delete[] mpImageList;
67 0 : maTBBorder1.disposeAndClear();
68 0 : maTBBorder2.disposeAndClear();
69 0 : maTBBorder3.disposeAndClear();
70 0 : maFL1.disposeAndClear();
71 0 : maFL2.disposeAndClear();
72 0 : svx::sidebar::PopupControl::dispose();
73 0 : }
74 :
75 0 : void CellBorderStyleControl::Initialize()
76 : {
77 0 : mpImageList = new Image[16];
78 0 : mpImageList[0] = Image(ScResId(IMG_BORDER1));
79 0 : mpImageList[1] = Image(ScResId(IMG_BORDER2));
80 0 : mpImageList[2] = Image(ScResId(IMG_BORDER3));
81 0 : mpImageList[3] = Image(ScResId(IMG_BORDER4));
82 0 : mpImageList[4] = Image(ScResId(IMG_BORDER5));
83 0 : mpImageList[5] = Image(ScResId(IMG_BORDER6));
84 0 : mpImageList[6] = Image(ScResId(IMG_BORDER7));
85 0 : mpImageList[7] = Image(ScResId(IMG_BORDER8));
86 0 : mpImageList[8] = Image(ScResId(IMG_BORDER9));
87 0 : mpImageList[9] = Image(ScResId(IMG_BORDER10));
88 0 : mpImageList[10] = Image(ScResId(IMG_BORDER11));
89 0 : mpImageList[11] = Image(ScResId(IMG_BORDER12));
90 0 : mpImageList[12] = Image(ScResId(IMG_BORDER13));
91 0 : mpImageList[13] = Image(ScResId(IMG_BORDER14));
92 0 : mpImageList[14] = Image(ScResId(IMG_BORDER15));
93 0 : mpImageList[15] = Image(ScResId(IMG_BORDER16));
94 :
95 0 : maTBBorder1->SetItemImage(TBI_BORDER1_NONE, mpImageList[0]);
96 0 : maTBBorder1->SetItemImage(TBI_BORDER1_ALL, mpImageList[1]);
97 0 : maTBBorder1->SetItemImage(TBI_BORDER1_OUTER, mpImageList[2]);
98 0 : maTBBorder1->SetItemImage(TBI_BORDER1_OUTERBOLD, mpImageList[3]);
99 0 : maTBBorder1->SetBackground(Wallpaper());
100 0 : maTBBorder1->SetPaintTransparent(true);
101 0 : Size aTbxSize( maTBBorder1->CalcWindowSizePixel() );
102 0 : maTBBorder1->SetOutputSizePixel( aTbxSize );
103 0 : maTBBorder1->SetSelectHdl ( LINK(this, CellBorderStyleControl, TB1SelectHdl) );
104 :
105 0 : maTBBorder2->SetLineCount(2);
106 0 : maTBBorder2->InsertItem(TBI_BORDER2_LEFT, mpImageList[4]);
107 0 : maTBBorder2->InsertItem(TBI_BORDER2_RIGHT, mpImageList[5]);
108 0 : maTBBorder2->InsertItem(TBI_BORDER2_TOP, mpImageList[6]);
109 0 : maTBBorder2->InsertItem(TBI_BORDER2_BOT, mpImageList[7]);
110 0 : maTBBorder2->InsertBreak();
111 0 : maTBBorder2->InsertItem(TBI_BORDER2_BLTR, mpImageList[8]);
112 0 : maTBBorder2->InsertItem(TBI_BORDER2_TLBR, mpImageList[9]);
113 0 : maTBBorder2->InsertItem(TBI_BORDER2_TOPBOT, mpImageList[10]);
114 0 : maTBBorder2->InsertItem(TBI_BORDER2_LEFTRIGHT, mpImageList[11]);
115 0 : maTBBorder2->SetBackground(Wallpaper());
116 0 : maTBBorder2->SetPaintTransparent(true);
117 0 : aTbxSize = maTBBorder2->CalcWindowSizePixel() ;
118 0 : maTBBorder2->SetOutputSizePixel( aTbxSize );
119 0 : maTBBorder2->SetHelpId(TBI_BORDER2_LEFT, HID_PROPERTYPANEL_SC_BORDER_TBI_LEFT);
120 0 : maTBBorder2->SetHelpId(TBI_BORDER2_RIGHT, HID_PROPERTYPANEL_SC_BORDER_TBI_RIGHT);
121 0 : maTBBorder2->SetHelpId(TBI_BORDER2_TOP, HID_PROPERTYPANEL_SC_BORDER_TBI_TOP);
122 0 : maTBBorder2->SetHelpId(TBI_BORDER2_BOT, HID_PROPERTYPANEL_SC_BORDER_TBI_BOT);
123 0 : maTBBorder2->SetHelpId(TBI_BORDER2_BLTR, HID_PROPERTYPANEL_SC_BORDER_TBI_BLTR);
124 0 : maTBBorder2->SetHelpId(TBI_BORDER2_TLBR, HID_PROPERTYPANEL_SC_BORDER_TBI_TLBR);
125 0 : maTBBorder2->SetHelpId(TBI_BORDER2_TOPBOT, HID_PROPERTYPANEL_SC_BORDER_TBI_TOPBOT);
126 0 : maTBBorder2->SetHelpId(TBI_BORDER2_LEFTRIGHT, HID_PROPERTYPANEL_SC_BORDER_TBI_LEFTRIGHT);
127 0 : maTBBorder2->SetItemText(TBI_BORDER2_LEFT, ScResId(STR_BORDER_1));
128 0 : maTBBorder2->SetItemText(TBI_BORDER2_RIGHT, ScResId(STR_BORDER_2));
129 0 : maTBBorder2->SetItemText(TBI_BORDER2_TOP, ScResId(STR_BORDER_3));
130 0 : maTBBorder2->SetItemText(TBI_BORDER2_BOT, ScResId(STR_BORDER_4));
131 0 : maTBBorder2->SetItemText(TBI_BORDER2_BLTR, ScResId(STR_BORDER_5));
132 0 : maTBBorder2->SetItemText(TBI_BORDER2_TLBR, ScResId(STR_BORDER_6));
133 0 : maTBBorder2->SetItemText(TBI_BORDER2_TOPBOT, ScResId(STR_BORDER_7));
134 0 : maTBBorder2->SetItemText(TBI_BORDER2_LEFTRIGHT, ScResId(STR_BORDER_8));
135 0 : maTBBorder2->SetSelectHdl ( LINK(this, CellBorderStyleControl, TB2SelectHdl) );
136 :
137 0 : maTBBorder3->SetItemImage(TBI_BORDER3_S1, mpImageList[12]);
138 0 : maTBBorder3->SetItemImage(TBI_BORDER3_S2, mpImageList[13]);
139 0 : maTBBorder3->SetItemImage(TBI_BORDER3_S3, mpImageList[14]);
140 0 : maTBBorder3->SetItemImage(TBI_BORDER3_S4, mpImageList[15]);
141 0 : maTBBorder3->SetBackground(Wallpaper());
142 0 : maTBBorder3->SetPaintTransparent(true);
143 0 : aTbxSize = maTBBorder3->CalcWindowSizePixel() ;
144 0 : maTBBorder3->SetOutputSizePixel( aTbxSize );
145 0 : maTBBorder3->SetSelectHdl ( LINK(this, CellBorderStyleControl, TB3SelectHdl) );
146 0 : }
147 :
148 0 : IMPL_LINK_TYPED(CellBorderStyleControl, TB1SelectHdl, ToolBox*, pToolBox, void)
149 : {
150 0 : sal_uInt16 nId = pToolBox->GetCurItemId();
151 0 : SvxBoxItem aBorderOuter( SID_ATTR_BORDER_OUTER );
152 0 : SvxBoxInfoItem aBorderInner( SID_ATTR_BORDER_INNER );
153 0 : editeng::SvxBorderLine theDefLine(NULL, 1);
154 0 : editeng::SvxBorderLine *pLeft = 0, *pRight = 0, *pTop = 0, *pBottom = 0;
155 0 : sal_uInt8 nValidFlags = 0;
156 0 : switch ( nId )
157 : {
158 : case TBI_BORDER1_NONE:
159 : {
160 0 : nValidFlags |= FRM_VALID_ALL;
161 0 : SvxLineItem aLineItem1( SID_ATTR_BORDER_DIAG_BLTR );
162 0 : SvxLineItem aLineItem2( SID_ATTR_BORDER_DIAG_TLBR );
163 0 : aLineItem1.SetLine( NULL ); //modify
164 0 : aLineItem2.SetLine( NULL ); //modify
165 0 : mrCellAppearancePropertyPanel.GetBindings()->GetDispatcher()->Execute(SID_ATTR_BORDER_DIAG_BLTR, SfxCallMode::RECORD, &aLineItem1, 0L);
166 0 : mrCellAppearancePropertyPanel.GetBindings()->GetDispatcher()->Execute(SID_ATTR_BORDER_DIAG_TLBR, SfxCallMode::RECORD, &aLineItem2, 0L);
167 : }
168 0 : break;
169 : case TBI_BORDER1_ALL:
170 0 : pLeft = pRight = pTop = pBottom = &theDefLine;
171 0 : aBorderInner.SetLine( &theDefLine, SvxBoxInfoItemLine::HORI );
172 0 : aBorderInner.SetLine( &theDefLine, SvxBoxInfoItemLine::VERT );
173 0 : nValidFlags |= FRM_VALID_ALL;
174 0 : break;
175 : case TBI_BORDER1_OUTER:
176 0 : pLeft = pRight = pTop = pBottom = &theDefLine;
177 0 : nValidFlags |= FRM_VALID_OUTER;
178 0 : break;
179 : case TBI_BORDER1_OUTERBOLD:
180 0 : theDefLine.SetWidth(DEF_LINE_WIDTH_2);
181 0 : pLeft = pRight = pTop = pBottom = &theDefLine;
182 0 : nValidFlags |= FRM_VALID_OUTER;
183 0 : break;
184 : }
185 :
186 0 : aBorderOuter.SetLine( pLeft, SvxBoxItemLine::LEFT );
187 0 : aBorderOuter.SetLine( pRight, SvxBoxItemLine::RIGHT );
188 0 : aBorderOuter.SetLine( pTop, SvxBoxItemLine::TOP );
189 0 : aBorderOuter.SetLine( pBottom, SvxBoxItemLine::BOTTOM );
190 :
191 0 : aBorderInner.SetValid( SvxBoxInfoItemValidFlags::TOP, 0 != (nValidFlags&FRM_VALID_TOP ));
192 0 : aBorderInner.SetValid( SvxBoxInfoItemValidFlags::BOTTOM, 0 != (nValidFlags&FRM_VALID_BOTTOM ));
193 0 : aBorderInner.SetValid( SvxBoxInfoItemValidFlags::LEFT, 0 != (nValidFlags&FRM_VALID_LEFT));
194 0 : aBorderInner.SetValid( SvxBoxInfoItemValidFlags::RIGHT, 0 != (nValidFlags&FRM_VALID_RIGHT ));
195 0 : aBorderInner.SetValid( SvxBoxInfoItemValidFlags::HORI, 0 != (nValidFlags&FRM_VALID_HINNER ));
196 0 : aBorderInner.SetValid( SvxBoxInfoItemValidFlags::VERT, 0 != (nValidFlags&FRM_VALID_VINNER));
197 0 : aBorderInner.SetValid( SvxBoxInfoItemValidFlags::DISTANCE, true );
198 0 : aBorderInner.SetValid( SvxBoxInfoItemValidFlags::DISABLE, false );
199 :
200 0 : mrCellAppearancePropertyPanel.GetBindings()->GetDispatcher()->Execute(SID_ATTR_BORDER, SfxCallMode::RECORD, &aBorderOuter, &aBorderInner, 0L);
201 0 : mrCellAppearancePropertyPanel.EndCellBorderStylePopupMode();
202 0 : }
203 :
204 0 : IMPL_LINK_TYPED(CellBorderStyleControl, TB2SelectHdl, ToolBox *, pToolBox, void)
205 : {
206 0 : sal_uInt16 nId = pToolBox->GetCurItemId();
207 :
208 0 : if( nId != TBI_BORDER2_BLTR && nId != TBI_BORDER2_TLBR )
209 : {
210 0 : SvxBoxItem aBorderOuter( SID_ATTR_BORDER_OUTER );
211 0 : SvxBoxInfoItem aBorderInner( SID_ATTR_BORDER_INNER );
212 0 : editeng::SvxBorderLine theDefLine(NULL, 1);
213 0 : editeng::SvxBorderLine *pLeft = 0,
214 0 : *pRight = 0,
215 0 : *pTop = 0,
216 0 : *pBottom = 0;
217 0 : sal_uInt8 nValidFlags = 0;
218 0 : switch ( nId )
219 : {
220 : case TBI_BORDER2_LEFT:
221 0 : pLeft = &theDefLine;
222 0 : nValidFlags |= FRM_VALID_LEFT;
223 0 : break;
224 : case TBI_BORDER2_RIGHT:
225 :
226 0 : if(!AllSettings::GetLayoutRTL())
227 : {
228 0 : pRight = &theDefLine;
229 0 : nValidFlags |= FRM_VALID_RIGHT;
230 : }
231 : else
232 : {
233 0 : pLeft = &theDefLine;
234 0 : nValidFlags |= FRM_VALID_LEFT;
235 : }
236 0 : break;
237 : case TBI_BORDER2_TOP:
238 0 : pTop = &theDefLine;
239 0 : nValidFlags |= FRM_VALID_TOP;
240 0 : break;
241 : case TBI_BORDER2_BOT:
242 0 : pBottom = &theDefLine;
243 0 : nValidFlags |= FRM_VALID_BOTTOM;
244 0 : break;
245 : case TBI_BORDER2_TOPBOT:
246 0 : pTop = pBottom = &theDefLine;
247 0 : nValidFlags |= FRM_VALID_BOTTOM|FRM_VALID_TOP;
248 0 : break;
249 : case TBI_BORDER2_LEFTRIGHT:
250 0 : pLeft = pRight = &theDefLine;
251 0 : nValidFlags |= FRM_VALID_RIGHT|FRM_VALID_LEFT;
252 0 : break;
253 : }
254 0 : aBorderOuter.SetLine( pLeft, SvxBoxItemLine::LEFT );
255 0 : aBorderOuter.SetLine( pRight, SvxBoxItemLine::RIGHT );
256 0 : aBorderOuter.SetLine( pTop, SvxBoxItemLine::TOP );
257 0 : aBorderOuter.SetLine( pBottom, SvxBoxItemLine::BOTTOM );
258 :
259 0 : aBorderInner.SetValid( SvxBoxInfoItemValidFlags::TOP, 0 != (nValidFlags&FRM_VALID_TOP ));
260 0 : aBorderInner.SetValid( SvxBoxInfoItemValidFlags::BOTTOM, 0 != (nValidFlags&FRM_VALID_BOTTOM ));
261 0 : aBorderInner.SetValid( SvxBoxInfoItemValidFlags::LEFT, 0 != (nValidFlags&FRM_VALID_LEFT));
262 0 : aBorderInner.SetValid( SvxBoxInfoItemValidFlags::RIGHT, 0 != (nValidFlags&FRM_VALID_RIGHT ));
263 0 : aBorderInner.SetValid( SvxBoxInfoItemValidFlags::HORI, 0 != (nValidFlags&FRM_VALID_HINNER ));
264 0 : aBorderInner.SetValid( SvxBoxInfoItemValidFlags::VERT, 0 != (nValidFlags&FRM_VALID_VINNER));
265 0 : aBorderInner.SetValid( SvxBoxInfoItemValidFlags::DISTANCE, true );
266 0 : aBorderInner.SetValid( SvxBoxInfoItemValidFlags::DISABLE, false );
267 :
268 0 : mrCellAppearancePropertyPanel.GetBindings()->GetDispatcher()->Execute(SID_ATTR_BORDER, SfxCallMode::RECORD, &aBorderOuter, &aBorderInner, 0L);
269 : }
270 0 : else if(nId == TBI_BORDER2_BLTR)
271 : {
272 0 : editeng::SvxBorderLine aTmp( NULL, 1 );
273 0 : SvxLineItem aLineItem( SID_ATTR_BORDER_DIAG_BLTR );
274 0 : aLineItem.SetLine( &aTmp );
275 0 : mrCellAppearancePropertyPanel.GetBindings()->GetDispatcher()->Execute(SID_ATTR_BORDER_DIAG_BLTR, SfxCallMode::RECORD, &aLineItem, 0L);
276 : }
277 0 : else if(nId == TBI_BORDER2_TLBR)
278 : {
279 0 : editeng::SvxBorderLine aTmp( NULL, 1 );
280 0 : SvxLineItem aLineItem( SID_ATTR_BORDER_DIAG_TLBR );
281 0 : aLineItem.SetLine( &aTmp );
282 0 : mrCellAppearancePropertyPanel.GetBindings()->GetDispatcher()->Execute(SID_ATTR_BORDER_DIAG_TLBR, SfxCallMode::RECORD, &aLineItem, 0L);
283 : }
284 :
285 0 : mrCellAppearancePropertyPanel.EndCellBorderStylePopupMode();
286 0 : }
287 :
288 0 : IMPL_LINK_TYPED(CellBorderStyleControl, TB3SelectHdl, ToolBox *, pToolBox, void)
289 : {
290 0 : sal_uInt16 nId = pToolBox->GetCurItemId();
291 :
292 0 : SvxBoxItem aBorderOuter( SID_ATTR_BORDER_OUTER );
293 0 : SvxBoxInfoItem aBorderInner( SID_ATTR_BORDER_INNER );
294 0 : boost::scoped_ptr<editeng::SvxBorderLine> pTop;
295 0 : boost::scoped_ptr<editeng::SvxBorderLine> pBottom;
296 0 : sal_uInt8 nValidFlags = 0;
297 : using namespace ::com::sun::star::table::BorderLineStyle;
298 :
299 : //FIXME: properly adapt to new line border model
300 :
301 0 : switch ( nId )
302 : {
303 : case TBI_BORDER3_S1:
304 0 : pBottom.reset(new editeng::SvxBorderLine(NULL, DEF_LINE_WIDTH_2 ));
305 0 : nValidFlags |= FRM_VALID_BOTTOM;
306 0 : break;
307 : case TBI_BORDER3_S2:
308 0 : pBottom.reset(new editeng::SvxBorderLine(NULL));
309 0 : pBottom->GuessLinesWidths(DOUBLE, DEF_LINE_WIDTH_0, DEF_LINE_WIDTH_0, DEF_LINE_WIDTH_1);
310 0 : nValidFlags |= FRM_VALID_BOTTOM;
311 0 : break;
312 : case TBI_BORDER3_S3:
313 0 : pBottom.reset(new editeng::SvxBorderLine(NULL, DEF_LINE_WIDTH_2 ));
314 0 : pTop.reset(new editeng::SvxBorderLine(NULL, 1));
315 0 : nValidFlags |= FRM_VALID_BOTTOM|FRM_VALID_TOP;
316 0 : break;
317 : case TBI_BORDER3_S4:
318 0 : pBottom.reset(new editeng::SvxBorderLine(NULL));
319 0 : pBottom->GuessLinesWidths(DOUBLE, DEF_LINE_WIDTH_0, DEF_LINE_WIDTH_0, DEF_LINE_WIDTH_1);
320 0 : pTop.reset(new editeng::SvxBorderLine(NULL, 1));
321 0 : nValidFlags |= FRM_VALID_BOTTOM|FRM_VALID_TOP;
322 0 : break;
323 : }
324 :
325 0 : aBorderOuter.SetLine( pTop.get(), SvxBoxItemLine::TOP );
326 0 : aBorderOuter.SetLine( pBottom.get(), SvxBoxItemLine::BOTTOM );
327 0 : aBorderOuter.SetLine( NULL, SvxBoxItemLine::LEFT );
328 0 : aBorderOuter.SetLine( NULL, SvxBoxItemLine::RIGHT );
329 :
330 0 : aBorderInner.SetValid( SvxBoxInfoItemValidFlags::TOP, 0 != (nValidFlags&FRM_VALID_TOP ));
331 0 : aBorderInner.SetValid( SvxBoxInfoItemValidFlags::BOTTOM, 0 != (nValidFlags&FRM_VALID_BOTTOM ));
332 0 : aBorderInner.SetValid( SvxBoxInfoItemValidFlags::LEFT, 0 != (nValidFlags&FRM_VALID_LEFT ));
333 0 : aBorderInner.SetValid( SvxBoxInfoItemValidFlags::RIGHT, 0 != (nValidFlags&FRM_VALID_RIGHT ));
334 0 : aBorderInner.SetValid( SvxBoxInfoItemValidFlags::HORI, 0 != (nValidFlags&FRM_VALID_HINNER ));
335 0 : aBorderInner.SetValid( SvxBoxInfoItemValidFlags::VERT, 0 != (nValidFlags&FRM_VALID_VINNER));
336 0 : aBorderInner.SetValid( SvxBoxInfoItemValidFlags::DISTANCE, true );
337 0 : aBorderInner.SetValid( SvxBoxInfoItemValidFlags::DISABLE, false );
338 :
339 0 : mrCellAppearancePropertyPanel.GetBindings()->GetDispatcher()->Execute(SID_ATTR_BORDER, SfxCallMode::RECORD, &aBorderOuter, &aBorderInner, 0L);
340 :
341 0 : pTop.reset();
342 0 : pBottom.reset();
343 :
344 0 : mrCellAppearancePropertyPanel.EndCellBorderStylePopupMode();
345 0 : }
346 :
347 156 : } } // end of namespace svx::sidebar
348 :
349 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|