5 Copyright (c) 2002 OpenBeOS.
12 Permission is hereby granted, free of charge, to any person obtaining a copy of
13 this software and associated documentation files (the "Software"), to deal in
14 the Software without restriction, including without limitation the rights to
15 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
16 of the Software, and to permit persons to whom the Software is furnished to do
17 so, subject to the following conditions:
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
32 2 Make Strings constants or UI resources
36 #include "MarginView.h"
41 #include <GridLayout.h>
42 #include <GroupLayout.h>
43 #include <GroupLayoutBuilder.h>
44 #include <SupportKit.h>
45 #include <TextControl.h>
52 /*----------------- MarginView Private Constants --------------------*/
54 const int kOffsetY
= 20;
55 const int kOffsetX
= 10;
56 const int kStringSize
= 50;
57 const int kWidth
= 50;
58 const int kNumCount
= 10;
60 const static float kPointUnits
= 1; // 1 point = 1 point
61 const static float kInchUnits
= 72; // 1" = 72 points
62 const static float kCMUnits
= 28.346; // 72/2.54 1cm = 28.346 points
64 const static float kMinFieldWidth
= 100; // pixels
65 const static float kMinUnitHeight
= 30; // pixels
67 const static float kUnitFormat
[] = { kInchUnits
, kCMUnits
, kPointUnits
};
68 const static char *kUnitNames
[] = { "inch", "cm", "points", NULL
};
69 const static MarginUnit kUnitMsg
[] = { kUnitInch
, kUnitCM
, kUnitPoint
};
71 const pattern kDots
= {{ 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 }};
73 const rgb_color kBlack
= { 0,0,0,0 };
74 const rgb_color kRed
= { 255,0,0,0 };
75 const rgb_color kWhite
= { 255,255,255,0 };
76 const rgb_color kGray
= { 220,220,220,0 };
80 : BView("pageView", B_WILL_DRAW
| B_FULL_UPDATE_ON_RESIZE
)
83 , fMargins(0, 0, 0, 0)
90 PageView::SetPageSize(float pageWidth
, float pageHeight
)
92 fPageWidth
= pageWidth
;
93 fPageHeight
= pageHeight
;
98 PageView::SetMargins(BRect margins
)
105 PageView::Draw(BRect bounds
)
107 BRect
frame(Frame());
108 float totalWidth
= frame
.Width();
109 float totalHeight
= frame
.Height();
111 // fit page into available space
112 // keeping the ratio fPageWidth : fPageHeight
113 float pageWidth
= totalWidth
;
114 float pageHeight
= totalWidth
* fPageHeight
/ fPageWidth
;
115 if (pageHeight
> totalHeight
) {
116 pageHeight
= totalHeight
;
117 pageWidth
= totalHeight
* fPageWidth
/ fPageHeight
;
122 offset
.x
= static_cast<int>((totalWidth
- pageWidth
) / 2);
123 offset
.y
= static_cast<int>((totalHeight
- pageHeight
) / 2);
126 SetHighColor(kWhite
);
127 BRect r
= BRect(0, 0, pageWidth
, pageHeight
);
130 SetHighColor(kBlack
);
136 r
.top
+= (fMargins
.top
/ fPageHeight
) * pageHeight
;
137 r
.right
-= (fMargins
.right
/ fPageWidth
) * pageWidth
;
138 r
.bottom
-= (fMargins
.bottom
/ fPageHeight
) * pageHeight
;
139 r
.left
+= (fMargins
.left
/ fPageWidth
) * pageWidth
;
140 StrokeRect(r
, kDots
);
147 * @param pageWidth, float that is the points value of the page width
148 * @param pageHeight, float that is the points value of the page height
149 * @param margins, BRect values of margins
150 * @param units, unit32 enum for units used in view
153 MarginView::MarginView(int32 pageWidth
, int32 pageHeight
,
154 BRect margins
, MarginUnit units
)
158 fUnitValue
= kUnitFormat
[units
];
164 fPageWidth
= pageWidth
;
165 fPageHeight
= pageHeight
;
175 MarginView::~MarginView()
187 MarginView::AttachedToWindow()
190 SetViewColor(Parent()->ViewColor());
199 * Receive messages for the view
201 * @param BMessage* , the message being received
205 MarginView::MessageReceived(BMessage
*msg
)
208 case CHANGE_PAGE_SIZE
: {
211 msg
->FindFloat("width", &w
);
212 msg
->FindFloat("height", &h
);
214 UpdateView(MARGIN_CHANGED
);
218 BPoint p
= PageSize();
219 SetPageSize(p
.y
, p
.x
);
220 UpdateView(MARGIN_CHANGED
);
224 UpdateView(MARGIN_CHANGED
);
227 case TOP_MARGIN_CHANGED
:
228 UpdateView(TOP_MARGIN_CHANGED
);
231 case LEFT_MARGIN_CHANGED
:
232 UpdateView(LEFT_MARGIN_CHANGED
);
235 case RIGHT_MARGIN_CHANGED
:
236 UpdateView(RIGHT_MARGIN_CHANGED
);
239 case BOTTOM_MARGIN_CHANGED
:
240 UpdateView(BOTTOM_MARGIN_CHANGED
);
243 case MARGIN_UNIT_CHANGED
: {
245 if (msg
->FindInt32("marginUnit", &marginUnit
) == B_OK
)
246 _SetMarginUnit((MarginUnit
)marginUnit
);
250 BView::MessageReceived(msg
);
256 /*----------------- MarginView Public Methods --------------------*/
262 * @return BPoint, contains actual point values of page in x, y of point
265 MarginView::PageSize() const
267 return BPoint(fPageWidth
, fPageHeight
);
274 * @param pageWidth, float that is the unit value of the page width
275 * @param pageHeight, float that is the unit value of the page height
279 MarginView::SetPageSize(float pageWidth
, float pageHeight
)
281 fPageWidth
= pageWidth
;
282 fPageHeight
= pageHeight
;
290 * @return rect, return margin values always in points
293 MarginView::Margin() const
297 // convert the field text to values
298 float top
= atof(fTop
->Text());
299 float right
= atof(fRight
->Text());
300 float left
= atof(fLeft
->Text());
301 float bottom
= atof(fBottom
->Text());
303 // convert to units to points
304 switch (fMarginUnit
) {
310 bottom
*= kInchUnits
;
323 margin
.Set(left
, top
, right
, bottom
);
334 * @return uint32 enum, units in inches, cm, points
337 MarginView::Unit() const
344 * UpdateView, recalculate and redraw the view
346 * @param msg is a message to the calculate size to tell which field caused
347 * the update to occur, or it is a general update.
351 MarginView::UpdateView(uint32 msg
)
356 char pageSize
[kStringSize
];
357 sprintf(pageSize
, "%2.1f x %2.1f",
358 fPageWidth
/ fUnitValue
,
359 fPageHeight
/ fUnitValue
);
360 fPageSize
->SetText(pageSize
);
362 fPage
->SetPageSize(fPageWidth
, fPageHeight
);
363 fPage
->SetMargins(Margin());
372 /*----------------- MarginView Private Methods --------------------*/
377 * Creates the GUI for the View. MUST be called AFTER the View is attached to
378 * the Window, or will crash and/or create strange behaviour
384 MarginView::_ConstructGUI()
386 fPage
= new PageView();
387 fPage
->SetViewColor(ViewColor());
389 fPageSize
= new BStringView("pageSize", "?x?");
392 // Create text fields
395 str
<< fMargins
.top
/fUnitValue
;
396 fTop
= new BTextControl("top", "Top:", str
.String(), NULL
);
398 fTop
->SetModificationMessage(new BMessage(TOP_MARGIN_CHANGED
));
399 fTop
->SetTarget(this);
400 _AllowOnlyNumbers(fTop
, kNumCount
);
404 str
<< fMargins
.left
/fUnitValue
;
405 fLeft
= new BTextControl("left", "Left:", str
.String(), NULL
);
407 fLeft
->SetModificationMessage(new BMessage(LEFT_MARGIN_CHANGED
));
408 fLeft
->SetTarget(this);
409 _AllowOnlyNumbers(fLeft
, kNumCount
);
413 str
<< fMargins
.bottom
/fUnitValue
;
414 fBottom
= new BTextControl("bottom", "Bottom:", str
.String(), NULL
);
416 fBottom
->SetModificationMessage(new BMessage(BOTTOM_MARGIN_CHANGED
));
417 fBottom
->SetTarget(this);
418 _AllowOnlyNumbers(fBottom
, kNumCount
);
422 str
<< fMargins
.right
/fUnitValue
;
423 fRight
= new BTextControl("right", "Right:", str
.String(), NULL
);
425 fRight
->SetModificationMessage(new BMessage(RIGHT_MARGIN_CHANGED
));
426 fRight
->SetTarget(this);
427 _AllowOnlyNumbers(fRight
, kNumCount
);
429 // Create Units popup
431 BPopUpMenu
*menu
= new BPopUpMenu("units");
432 BMenuField
*units
= new BMenuField("units", "Units:", menu
);
435 // Construct menu items
436 for (int32 i
= 0; kUnitNames
[i
] != NULL
; i
++) {
437 BMessage
*msg
= new BMessage(MARGIN_UNIT_CHANGED
);
438 msg
->AddInt32("marginUnit", kUnitMsg
[i
]);
439 menu
->AddItem(item
= new BMenuItem(kUnitNames
[i
], msg
));
440 item
->SetTarget(this);
441 if (fMarginUnit
== kUnitMsg
[i
])
442 item
->SetMarked(true);
445 BGridView
* settings
= new BGridView();
446 BGridLayout
* settingsLayout
= settings
->GridLayout();
447 settingsLayout
->AddItem(fTop
->CreateLabelLayoutItem(), 0, 0);
448 settingsLayout
->AddItem(fTop
->CreateTextViewLayoutItem(), 1, 0);
449 settingsLayout
->AddItem(fLeft
->CreateLabelLayoutItem(), 0, 1);
450 settingsLayout
->AddItem(fLeft
->CreateTextViewLayoutItem(), 1, 1);
451 settingsLayout
->AddItem(fBottom
->CreateLabelLayoutItem(), 0, 2);
452 settingsLayout
->AddItem(fBottom
->CreateTextViewLayoutItem(), 1, 2);
453 settingsLayout
->AddItem(fRight
->CreateLabelLayoutItem(), 0, 3);
454 settingsLayout
->AddItem(fRight
->CreateTextViewLayoutItem(), 1, 3);
455 settingsLayout
->AddItem(units
->CreateLabelLayoutItem(), 0, 4);
456 settingsLayout
->AddItem(units
->CreateMenuBarLayoutItem(), 1, 4);
457 settingsLayout
->SetSpacing(0, 0);
459 BGroupView
* groupView
= new BGroupView(B_HORIZONTAL
, 10);
460 BGroupLayout
* groupLayout
= groupView
->GroupLayout();
461 groupLayout
->AddView(BGroupLayoutBuilder(B_VERTICAL
, 0)
464 .SetInsets(0, 0, 0, 0)
467 groupLayout
->AddView(settings
);
468 groupLayout
->SetInsets(5, 5, 5, 5);
472 UpdateView(MARGIN_CHANGED
);
479 * @param BTextControl, the control we want to only allow numbers
480 * @param maxNum, the maximun number of characters allowed
484 MarginView::_AllowOnlyNumbers(BTextControl
*textControl
, int32 maxNum
)
486 BTextView
*tv
= textControl
->TextView();
488 for (int32 i
= 0; i
< 256; i
++)
491 for (int32 i
= '0'; i
<= '9'; i
++)
494 tv
->AllowChar(B_BACKSPACE
);
495 // TODO internationalization; e.g. "." or ","
497 tv
->SetMaxBytes(maxNum
);
503 * @param brect, margin values in rect
507 MarginView::_SetMargin(BRect margin
)
514 * SetUnits, called by the MarginMgr when the units popup is selected
516 * @param uint32, the enum that identifies the units requested to change to.
520 MarginView::_SetMarginUnit(MarginUnit unit
)
522 // do nothing if the current units are the same as requested
523 if (unit
== fMarginUnit
) {
527 // set the units Format
528 fUnitValue
= kUnitFormat
[unit
];
530 // convert the field text to values
531 float top
= atof(fTop
->Text());
532 float right
= atof(fRight
->Text());
533 float left
= atof(fLeft
->Text());
534 float bottom
= atof(fBottom
->Text());
536 // convert to target units
544 bottom
*= kInchUnits
;
545 // check for target unit is cm
546 if (unit
== kUnitCM
) {
559 // check for target unit is inches
560 if (unit
== kUnitInch
) {
564 bottom
/= kInchUnits
;
568 // check for target unit is cm
569 if (unit
== kUnitCM
) {
575 // check for target unit is inches
576 if (unit
== kUnitInch
) {
580 bottom
/= kInchUnits
;
586 // lock Window since these changes are from another thread
589 // set the fields to new units
592 fTop
->SetText(str
.String());
596 fLeft
->SetText(str
.String());
600 fRight
->SetText(str
.String());
604 fBottom
->SetText(str
.String());