From 5a43a018cfc50f9c04fd2523e6bf84fabf9a1363 Mon Sep 17 00:00:00 2001 From: Markus Gans Date: Sun, 11 Aug 2019 18:15:57 +0200 Subject: [PATCH] FRect has now got a scaleBy() method --- ChangeLog | 4 + examples/7segment.cpp | 3 +- examples/mouse.cpp | 7 +- src/fdialog.cpp | 33 +++---- src/flistbox.cpp | 32 +++--- src/flistview.cpp | 31 +++--- src/frect.cpp | 20 +++- src/fscrollview.cpp | 6 +- src/fwidget.cpp | 177 ++++++++++++++++------------------ src/fwindow.cpp | 36 +++---- src/include/final/flistbox.h | 1 + src/include/final/flistview.h | 1 + src/include/final/frect.h | 2 + src/include/final/fwidget.h | 20 ++-- test/frect-test.cpp | 36 ++++++- 15 files changed, 238 insertions(+), 171 deletions(-) diff --git a/ChangeLog b/ChangeLog index e9dcaae4..f2a426ae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2019-08-11 Markus Gans + * FRect has now got a scaleBy() method + * Convert drawBorder() to a non-member function using FRect + 2019-08-10 Markus Gans * Pitch and duration of system speaker can now be changed on OpenBSD diff --git a/examples/7segment.cpp b/examples/7segment.cpp index 2d9b6f52..b784c0cd 100644 --- a/examples/7segment.cpp +++ b/examples/7segment.cpp @@ -27,6 +27,7 @@ namespace fc = finalcut::fc; using finalcut::FColorPair; +using finalcut::FRect; using finalcut::FPoint; using finalcut::FSize; @@ -199,7 +200,7 @@ void SegmentView::draw() FDialog::draw(); setColor(fc::LightGray, fc::Black); - FWidget::drawBorder(3, 6, 40, 11); + finalcut::drawBorder(this, FRect(FPoint(3, 6), FPoint(40, 11))); for (auto&& ch : Input.getText().toUpper()) { diff --git a/examples/mouse.cpp b/examples/mouse.cpp index 388e1274..5145a64b 100644 --- a/examples/mouse.cpp +++ b/examples/mouse.cpp @@ -23,9 +23,10 @@ #include namespace fc = finalcut::fc; +using finalcut::FColorPair; +using finalcut::FRect; using finalcut::FPoint; using finalcut::FSize; -using finalcut::FColorPair; //---------------------------------------------------------------------- @@ -129,7 +130,7 @@ void ColorChooser::onMouseDown (finalcut::FMouseEvent* ev) void ColorChooser::draw() { setColor(); - finalcut::FWidget::drawBorder (1, 2, 8, 11); + finalcut::drawBorder (this, FRect(FPoint(1, 2), FSize(8, 10))); for (FColor c = 0; c < 16; c++) { @@ -243,7 +244,7 @@ void Brushes::draw() { int pos; setColor(); - finalcut::FWidget::drawBorder (1, 2, 8, 4); + finalcut::drawBorder (this, FRect(FPoint(1, 2), FSize(8, 3))); print() << FPoint(2, 3) << FColorPair(fg_color, bg_color) << " " << finalcut::FString(3, fc::MediumShade); diff --git a/src/fdialog.cpp b/src/fdialog.cpp index 10ac314a..5db733de 100644 --- a/src/fdialog.cpp +++ b/src/fdialog.cpp @@ -913,39 +913,38 @@ void FDialog::initCloseMenuItem (FMenu* menu) //---------------------------------------------------------------------- void FDialog::drawBorder() { - int x1 = 1 - , x2 = 1 + int(getWidth()) - 1 - , y1 = 2 - , y2 = 1 + int(getHeight()) - 1; - if ( (getMoveSizeWidget() == this || ! resize_click_pos.isOrigin() ) && ! isZoomed() ) setColor (wc.dialog_resize_fg, getBackgroundColor()); else setColor(); - if ( isNewFont() ) + if ( isNewFont() ) // Draw a newfont U-shaped frame { - for (int y = y1; y < y2; y++) + FRect r(FPoint(1, 1), getSize()); + + for (int y = r.getY1() + 1; y < r.getY2(); y++) { - print() << FPoint(x1, y) // Border left ⎸ - << fc::NF_border_line_left; - print() << FPoint(x2, y) // Border right⎹ - << fc::NF_rev_border_line_right; + print() << FPoint(r.getX1(), y) + << fc::NF_border_line_left // border left ⎸ + << FPoint(r.getX2(), y) + << fc::NF_rev_border_line_right; // border right⎹ } - print() << FPoint(x1, y2) // Lower left corner border ⎣ + print() << r.getLowerLeftPos() // lower left corner border ⎣ << fc::NF_border_corner_lower_left; - for (std::size_t x = 1; x < getWidth() - 1; x++) // low line _ - print (fc::NF_border_line_bottom); + for (int x = r.getX1() + 1; x < r.getX2(); x++) + print (fc::NF_border_line_bottom); // low line _ - print() << FPoint(x2, y2) // Lower right corner border ⎦ - << fc::NF_rev_border_corner_lower_right; + // lower right corner border ⎦ + print (fc::NF_rev_border_corner_lower_right); } else { - FWidget::drawBorder(x1, y1, x2, y2); + FRect box(FPoint(1, 2), getSize()); + box.scaleBy(0, -1); + finalcut::drawBorder(this, box); } } diff --git a/src/flistbox.cpp b/src/flistbox.cpp index c42e9f32..cab1503f 100644 --- a/src/flistbox.cpp +++ b/src/flistbox.cpp @@ -816,7 +816,11 @@ void FListBox::draw() setReverse(true); if ( isNewFont() ) - drawBorder (1, 1, int(getWidth()) - 1, int(getHeight())); + { + FRect box(FPoint(1, 1), getSize()); + box.scaleBy(-1, 0); + finalcut::drawBorder (this, box); + } else drawBorder(); @@ -836,16 +840,7 @@ void FListBox::draw() if ( isMonochron() ) setReverse(false); - if ( ! hbar->isShown() && isHorizontallyScrollable() ) - hbar->show(); - else - vbar->redraw(); - - if ( ! vbar->isShown() && isVerticallyScrollable() ) - vbar->show(); - else - hbar->redraw(); - + drawScrollbars(); drawList(); if ( flags.focus && getStatusBar() ) @@ -861,6 +856,21 @@ void FListBox::draw() } } +//---------------------------------------------------------------------- +void FListBox::drawScrollbars() +{ + if ( ! hbar->isShown() && isHorizontallyScrollable() ) + hbar->show(); + else + vbar->redraw(); + + if ( ! vbar->isShown() && isVerticallyScrollable() ) + vbar->show(); + else + hbar->redraw(); +} + + //---------------------------------------------------------------------- void FListBox::drawHeadline() { diff --git a/src/flistview.cpp b/src/flistview.cpp index 928055f7..973f261a 100644 --- a/src/flistview.cpp +++ b/src/flistview.cpp @@ -1476,7 +1476,11 @@ void FListView::draw() setReverse(true); if ( isNewFont() ) - drawBorder (1, 1, int(getWidth()) - 1, int(getHeight())); + { + FRect box(FPoint(1, 1), getSize()); + box.scaleBy(-1, 0); + finalcut::drawBorder (this, box); + } else drawBorder(); @@ -1496,16 +1500,7 @@ void FListView::draw() if ( isMonochron() ) setReverse(false); - if ( ! hbar->isShown() && isHorizontallyScrollable() ) - hbar->show(); - else - vbar->redraw(); - - if ( ! vbar->isShown() && isVerticallyScrollable() ) - vbar->show(); - else - hbar->redraw(); - + drawScrollbars(); drawList(); if ( flags.focus && getStatusBar() ) @@ -1521,6 +1516,20 @@ void FListView::draw() } } +//---------------------------------------------------------------------- +void FListView::drawScrollbars() +{ + if ( ! hbar->isShown() && isHorizontallyScrollable() ) + hbar->show(); + else + vbar->redraw(); + + if ( ! vbar->isShown() && isVerticallyScrollable() ) + vbar->show(); + else + hbar->redraw(); +} + //---------------------------------------------------------------------- void FListView::drawHeadlines() { diff --git a/src/frect.cpp b/src/frect.cpp index cef8954f..dd33c125 100644 --- a/src/frect.cpp +++ b/src/frect.cpp @@ -171,10 +171,10 @@ void FRect::setHeight (std::size_t h) } //---------------------------------------------------------------------- -void FRect::setSize (std::size_t w, std::size_t h) +void FRect::setSize (std::size_t width, std::size_t height) { - X2 = X1 + int(w) - 1; - Y2 = Y1 + int(h) - 1; + X2 = X1 + int(width) - 1; + Y2 = Y1 + int(height) - 1; } //---------------------------------------------------------------------- @@ -244,6 +244,20 @@ void FRect::move (const FPoint& d) Y2 = Y2 + d.getY(); } +//---------------------------------------------------------------------- +void FRect::scaleBy (int dx, int dy) +{ + X2 += dx; + Y2 += dy; +} + +//---------------------------------------------------------------------- +void FRect::scaleBy (const FPoint& d) +{ + X2 += d.getX(); + Y2 += d.getY(); +} + //---------------------------------------------------------------------- bool FRect::contains (int x, int y) const { diff --git a/src/fscrollview.cpp b/src/fscrollview.cpp index f460976e..4ce682b9 100644 --- a/src/fscrollview.cpp +++ b/src/fscrollview.cpp @@ -432,7 +432,11 @@ void FScrollView::draw() if ( border ) { if ( isNewFont() ) - drawBorder (1, 1, int(getWidth()) - 1, int(getHeight())); + { + FRect box(FPoint(1, 1), getSize()); + box.scaleBy(-1, 0); + finalcut::drawBorder (this, box); + } else drawBorder(); } diff --git a/src/fwidget.cpp b/src/fwidget.cpp index b41772a8..0b949af2 100644 --- a/src/fwidget.cpp +++ b/src/fwidget.cpp @@ -1419,33 +1419,6 @@ void FWidget::clearFlatBorder() } } -//---------------------------------------------------------------------- -void FWidget::drawBorder (int x1, int y1, int x2, int y2) -{ - if ( x1 > x2 ) - std::swap (x1, x2); - - if ( y1 > y2 ) - std::swap (y1, y2); - - if ( x1 < 1 ) - x1 = 1; - - if ( y1 < 1 ) - y1 = 1; - - if ( x2 > int(getWidth()) ) - x2 = int(getWidth()); - - if ( y2 > int(getHeight()) ) - y2 = int(getHeight()); - - if ( isNewFont() ) - drawNewFontBox (x1, y1, x2, y2); - else - drawBox (x1, y1, x2, y2); -} - //---------------------------------------------------------------------- void FWidget::quit() { @@ -2302,72 +2275,6 @@ void FWidget::drawBlockShadow (int x1, int y1, int x2, int y2) unsetInheritBackground(); } -//---------------------------------------------------------------------- -inline void FWidget::drawBox (int x1, int y1, int x2, int y2) -{ - // Use box-drawing characters to draw a border - - print() << FPoint(x1, y1) << fc::BoxDrawingsDownAndRight; // ┌ - - for (int x = x1 + 1; x < x2; x++) - print (fc::BoxDrawingsHorizontal); // ─ - - print (fc::BoxDrawingsDownAndLeft); // ┐ - - for (int y = y1 + 1; y < y2; y++) - { - print() << FPoint(x1, y) - << fc::BoxDrawingsVertical // │ - << FPoint(x2, y) - << fc::BoxDrawingsVertical; // │ - } - - print() << FPoint(x1, y2) << fc::BoxDrawingsUpAndRight; // └ - - for (int x = x1 + 1; x < x2; x++) - print (fc::BoxDrawingsHorizontal); // ─ - - print (fc::BoxDrawingsUpAndLeft); // ┘ - - for (int x = x1 + 1; x < x2; x++) - { - print() << FPoint(x, y1) - << fc::BoxDrawingsHorizontal // ─ - << FPoint(x, y2) - << fc::BoxDrawingsHorizontal; // ─ - } -} - -//---------------------------------------------------------------------- -inline void FWidget::drawNewFontBox (int x1, int y1, int x2, int y2) -{ - // Use new graphical font characters to draw a border - - print() << FPoint(x1, y1) - << fc::NF_border_corner_middle_upper_left; // ┌ - - for (int x = x1 + 1; x < x2; x++) - print (fc::BoxDrawingsHorizontal); // ─ - - print (fc::NF_border_corner_middle_upper_right); // ┐ - - for (int y = y1 + 1; y <= y2; y++) - { - print() << FPoint(x1, y) - << fc::NF_border_line_left // border left ⎸ - << FPoint(x2, y) - << fc::NF_rev_border_line_right; // border right⎹ - } - - print() << FPoint(x1, y2) - << fc::NF_border_corner_middle_lower_left; // └ - - for (int x = x1 + 1; x < x2; x++) - print (fc::BoxDrawingsHorizontal); // ─ - - print (fc::NF_border_corner_middle_lower_right); // ┘ -} - //---------------------------------------------------------------------- void FWidget::setColorTheme() { @@ -2433,4 +2340,88 @@ FKey getHotkey (const FString& text) return 0; } +//---------------------------------------------------------------------- +inline void drawBox (FWidget* w, const FRect& r) +{ + // Use box-drawing characters to draw a border + + w->print() << r.getUpperLeftPos() << fc::BoxDrawingsDownAndRight; // ┌ + + for (int x = r.getX1() + 1; x < r.getX2(); x++) + w->print (fc::BoxDrawingsHorizontal); // ─ + + w->print (fc::BoxDrawingsDownAndLeft); // ┐ + + for (int y = r.getY1() + 1; y < r.getY2(); y++) + { + w->print() << FPoint(r.getX1(), y) + << fc::BoxDrawingsVertical // │ + << FPoint(r.getX2(), y) + << fc::BoxDrawingsVertical; // │ + } + + w->print() << r.getLowerLeftPos() << fc::BoxDrawingsUpAndRight; // └ + + for (int x = r.getX1() + 1; x < r.getX2(); x++) + w->print (fc::BoxDrawingsHorizontal); // ─ + + w->print (fc::BoxDrawingsUpAndLeft); // ┘ +} + +//---------------------------------------------------------------------- +inline void drawNewFontBox (FWidget* w, const FRect& r) +{ + // Use new graphical font characters to draw a border + + w->print() << r.getUpperLeftPos() + << fc::NF_border_corner_middle_upper_left; // ┌ + for (int x = r.getX1() + 1; x < r.getX2(); x++) + w->print (fc::BoxDrawingsHorizontal); // ─ + + w->print (fc::NF_border_corner_middle_upper_right); // ┐ + + for (int y = r.getY1() + 1; y < r.getY2(); y++) + { + w->print() << FPoint(r.getX1(), y) + << fc::NF_border_line_left // border left ⎸ + << FPoint(r.getX2(), y) + << fc::NF_rev_border_line_right; // border right⎹ + } + + w->print() << r.getLowerLeftPos() + << fc::NF_border_corner_middle_lower_left; // └ + + for (int x = r.getX1() + 1; x < r.getX2(); x++) + w->print (fc::BoxDrawingsHorizontal); // ─ + + w->print (fc::NF_border_corner_middle_lower_right); // ┘ +} + +//---------------------------------------------------------------------- +void drawBorder (FWidget* w, FRect r) +{ + if ( r.x1_ref() > r.x2_ref() ) + std::swap (r.x1_ref(), r.x2_ref()); + + if ( r.y1_ref() > r.y2_ref() ) + std::swap (r.y1_ref(), r.y2_ref()); + + if ( r.x1_ref() < 1 ) + r.x1_ref() = 1; + + if ( r.y1_ref() < 1 ) + r.y1_ref() = 1; + + if ( r.x2_ref() > int(w->getWidth()) ) + r.x2_ref() = int(w->getWidth()); + + if ( r.y2_ref() > int(w->getHeight()) ) + r.y2_ref() = int(w->getHeight()); + + if ( w->isNewFont() ) + drawNewFontBox (w, r); + else + drawBox (w, r); +} + } // namespace finalcut diff --git a/src/fwindow.cpp b/src/fwindow.cpp index 7c897bec..5cfc4c5d 100644 --- a/src/fwindow.cpp +++ b/src/fwindow.cpp @@ -247,36 +247,32 @@ bool FWindow::isWindowHidden() const //---------------------------------------------------------------------- void FWindow::drawBorder() { - if ( isNewFont() ) + if ( isNewFont() ) // Draw a newfont outer frame { - int x1 = 1 - , x2 = 1 + int(getWidth()) - 1 - , y1 = 1 - , y2 = 1 + int(getHeight()) - 1; - - print() << FPoint(x1, y1) << fc::NF_border_corner_upper_left; // ⎡ - - for (int x = x1 + 1; x < x2; x++) - print (fc::NF_border_line_upper); // ¯ + FRect r(FPoint(1, 1), getSize()); + print() << r.getUpperLeftPos() + << fc::NF_border_corner_upper_left; // ⎡ + for (int x = r.getX1() + 1; x < r.getX2(); x++) + print (fc::NF_border_line_upper); // ¯ print (fc::NF_rev_border_corner_upper_right); // ⎤ - for (int y = y1 + 1; y < y2; y++) + for (int y = r.getY1() + 1; y < r.getY2(); y++) { - print() << FPoint(x1, y) // border left ⎸ - << fc::NF_border_line_left - << FPoint(x2, y) // border right⎹ - << fc::NF_rev_border_line_right; + print() << FPoint(r.getX1(), y) + << fc::NF_border_line_left // border left ⎸ + << FPoint(r.getX2(), y) + << fc::NF_rev_border_line_right; // border right⎹ } - print() << FPoint(x1, y2) // lower left corner border ⎣ + print() << r.getLowerLeftPos() // lower left corner border ⎣ << fc::NF_border_corner_lower_left; - for (std::size_t x = 2; x < getWidth(); x++) // low line _ - print (fc::NF_border_line_bottom); + for (int x = r.getX1() + 1; x < r.getX2(); x++) + print (fc::NF_border_line_bottom); // low line _ - print() << FPoint(x2, y2) // lower right corner border ⎦ - << fc::NF_rev_border_corner_lower_right; + // lower right corner border ⎦ + print (fc::NF_rev_border_corner_lower_right); } else { diff --git a/src/include/final/flistbox.h b/src/include/final/flistbox.h index 933cec61..5363f3a1 100644 --- a/src/include/final/flistbox.h +++ b/src/include/final/flistbox.h @@ -268,6 +268,7 @@ class FListBox : public FWidget , fc::orientation , FListBoxCallback ); void draw() override; + void drawScrollbars(); void drawHeadline(); void drawList(); void drawListLine (int, listBoxItems::iterator, bool); diff --git a/src/include/final/flistview.h b/src/include/final/flistview.h index 0152e7a4..fe5a838e 100644 --- a/src/include/final/flistview.h +++ b/src/include/final/flistview.h @@ -394,6 +394,7 @@ class FListView : public FWidget , std::size_t , std::size_t ); void draw() override; + void drawScrollbars(); void drawHeadlines(); void drawList(); void drawListLine (const FListViewItem*, bool, bool); diff --git a/src/include/final/frect.h b/src/include/final/frect.h index 179a416a..5631bb2a 100644 --- a/src/include/final/frect.h +++ b/src/include/final/frect.h @@ -128,6 +128,8 @@ class FRect // Methods void move (int, int); void move (const FPoint&); + void scaleBy (int, int); + void scaleBy (const FPoint&); bool contains (int, int) const; bool contains (const FPoint&) const; bool contains (const FRect&) const; diff --git a/src/include/final/fwidget.h b/src/include/final/fwidget.h index 9372a286..56898d9a 100644 --- a/src/include/final/fwidget.h +++ b/src/include/final/fwidget.h @@ -339,7 +339,6 @@ class FWidget : public FVTerm, public FObject void clearShadow(); void drawFlatBorder(); void clearFlatBorder(); - virtual void drawBorder (int, int, int, int); virtual void drawBorder(); static void quit(); @@ -431,8 +430,6 @@ class FWidget : public FVTerm, public FObject void drawChildren(); void drawTransparentShadow (int, int, int, int); void drawBlockShadow (int, int, int, int); - void drawBox (int, int, int, int); - void drawNewFontBox (int, int, int, int); static void setColorTheme(); // Data Members @@ -523,6 +520,13 @@ class FWidget : public FVTerm, public FObject #pragma pack(pop) +// non-member function forward declarations +//---------------------------------------------------------------------- +char* createBlankArray (std::size_t); +void destroyBlankArray (char[]); +FKey getHotkey (const FString&); +void drawBorder (FWidget*, FRect); + // FWidget inline functions //---------------------------------------------------------------------- inline const char* FWidget::getClassName() const @@ -937,7 +941,9 @@ inline void FWidget::print (const FPoint& pos) //---------------------------------------------------------------------- inline void FWidget::drawBorder() -{ drawBorder (1, 1, int(getWidth()), int(getHeight())); } +{ + finalcut::drawBorder (this, FRect(FPoint(1, 1), getSize())); +} //---------------------------------------------------------------------- inline void FWidget::processDestroy() @@ -1005,12 +1011,6 @@ const wchar_t CHECKED_RADIO_BUTTON[4] = '\0' }; -// non-member function forward declarations -//---------------------------------------------------------------------- -char* createBlankArray (std::size_t); -void destroyBlankArray (char[]); -FKey getHotkey (const FString&); - } // namespace finalcut #endif // FWIDGET_H diff --git a/test/frect-test.cpp b/test/frect-test.cpp index 6d31b126..e0ad0a2b 100644 --- a/test/frect-test.cpp +++ b/test/frect-test.cpp @@ -56,6 +56,7 @@ class FRectTest : public CPPUNIT_NS::TestFixture void subtractionTest(); void referenceTest(); void moveTest(); + void scaleTest(); void containsTest(); void overlapTest(); void intersectTest(); @@ -79,6 +80,7 @@ class FRectTest : public CPPUNIT_NS::TestFixture CPPUNIT_TEST (subtractionTest); CPPUNIT_TEST (referenceTest); CPPUNIT_TEST (moveTest); + CPPUNIT_TEST (scaleTest); CPPUNIT_TEST (containsTest); CPPUNIT_TEST (overlapTest); CPPUNIT_TEST (intersectTest); @@ -478,7 +480,7 @@ void FRectTest::moveTest() CPPUNIT_ASSERT ( r1.getX2() == 10 ); CPPUNIT_ASSERT ( r1.getY2() == 21 ); - const finalcut::FPoint p1 (2,3); + const finalcut::FPoint p1 (2, 3); r1.move(p1); CPPUNIT_ASSERT ( r1.getX() == 3 ); CPPUNIT_ASSERT ( r1.getY() == 5 ); @@ -498,6 +500,38 @@ void FRectTest::moveTest() CPPUNIT_ASSERT ( r1.getY2() == 19 ); } +//---------------------------------------------------------------------- +void FRectTest::scaleTest() +{ + finalcut::FRect r1 (finalcut::FPoint(5, 5), finalcut::FSize(15, 15)); + CPPUNIT_ASSERT ( r1.getX() == 5 ); + CPPUNIT_ASSERT ( r1.getY() == 5 ); + CPPUNIT_ASSERT ( r1.getWidth() == 15 ); + CPPUNIT_ASSERT ( r1.getHeight() == 15 ); + CPPUNIT_ASSERT ( r1.getSize() == finalcut::FSize(15, 15) ); + CPPUNIT_ASSERT ( r1.getX2() == 19 ); + CPPUNIT_ASSERT ( r1.getY2() == 19 ); + + const finalcut::FPoint p1 (-2, -3); + r1.scaleBy(p1); + CPPUNIT_ASSERT ( r1.getX() == 5 ); + CPPUNIT_ASSERT ( r1.getY() == 5 ); + CPPUNIT_ASSERT ( r1.getWidth() == 13 ); + CPPUNIT_ASSERT ( r1.getHeight() == 12 ); + CPPUNIT_ASSERT ( r1.getSize() == finalcut::FSize(13, 12) ); + CPPUNIT_ASSERT ( r1.getX2() == 17 ); + CPPUNIT_ASSERT ( r1.getY2() == 16 ); + + r1.scaleBy(1, -1); + CPPUNIT_ASSERT ( r1.getX() == 5 ); + CPPUNIT_ASSERT ( r1.getY() == 5 ); + CPPUNIT_ASSERT ( r1.getWidth() == 14 ); + CPPUNIT_ASSERT ( r1.getHeight() == 11 ); + CPPUNIT_ASSERT ( r1.getSize() == finalcut::FSize(14, 11) ); + CPPUNIT_ASSERT ( r1.getX2() == 18 ); + CPPUNIT_ASSERT ( r1.getY2() == 15 ); +} + //---------------------------------------------------------------------- void FRectTest::containsTest() {