Kaydet (Commit) e2fcb76d authored tarafından Caolán McNamara's avatar Caolán McNamara

weld SwSectionIndentTabPage

Change-Id: I961686c1257f0d85686df06aa7c73c324d0f70b8
Reviewed-on: https://gerrit.libreoffice.org/55387Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarCaolán McNamara <caolanm@redhat.com>
Tested-by: 's avatarCaolán McNamara <caolanm@redhat.com>
üst 8015cd21
......@@ -17,6 +17,7 @@
class DateTime;
class LocaleDataWrapper;
namespace vcl { class Window; }
class OutputDevice;
class VclBuilderContainer;
//when two tab pages both have the same basic layout with a preview on the
......@@ -28,7 +29,7 @@ class VclBuilderContainer;
//except for the preview widget
void SFX2_DLLPUBLIC setPreviewsToSamePlace(vcl::Window const *pParent, VclBuilderContainer *pPage);
Size SFX2_DLLPUBLIC getParagraphPreviewOptimalSize(const vcl::Window *pReference);
Size SFX2_DLLPUBLIC getParagraphPreviewOptimalSize(const OutputDevice& rReference);
Size SFX2_DLLPUBLIC getDrawPreviewOptimalSize(const vcl::Window *pReference);
......
......@@ -19,6 +19,7 @@
#ifndef INCLUDED_SVX_PARAPREV_HXX
#define INCLUDED_SVX_PARAPREV_HXX
#include <vcl/customweld.hxx>
#include <vcl/window.hxx>
#include <editeng/svxenum.hxx>
#include <svx/svxdllapi.h>
......@@ -111,6 +112,81 @@ public:
}
};
class SVX_DLLPUBLIC ParaPrevWindow final : public weld::CustomWidgetController
{
Size aSize;
// indentation
long nLeftMargin;
long nRightMargin;
short nFirstLineOfst;
// distances
sal_uInt16 nUpper;
sal_uInt16 nLower;
// adjustment
SvxAdjust eAdjust;
// last line in justification
SvxAdjust eLastLine;
// line distance
SvxPrevLineSpace eLine;
OUString aText;
tools::Rectangle Lines[9];
virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override;
virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override;
void DrawParagraph(vcl::RenderContext& rRenderContext);
public:
ParaPrevWindow();
void SetFirstLineOfst( short nNew )
{
nFirstLineOfst = nNew;
}
void SetLeftMargin( long nNew )
{
nLeftMargin = nNew;
}
void SetRightMargin( long nNew )
{
nRightMargin = nNew;
}
void SetUpper( sal_uInt16 nNew )
{
nUpper = nNew;
}
void SetLower( sal_uInt16 nNew )
{
nLower = nNew;
}
void SetAdjust( SvxAdjust eNew )
{
eAdjust = eNew;
}
void SetLastLine( SvxAdjust eNew )
{
eLastLine = eNew;
}
void SetLineSpace( SvxPrevLineSpace eNew )
{
eLine = eNew;
}
void SetText( const OUString& rStr )
{
aText = rStr;
}
void SetSize( Size aNew )
{
aSize = aNew;
}
OUString GetText() const
{
return aText;
}
};
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
......@@ -52,9 +52,9 @@ void setPreviewsToSamePlace(vcl::Window const *pParent, VclBuilderContainer *pPa
}
}
Size getParagraphPreviewOptimalSize(const vcl::Window *pReference)
Size getParagraphPreviewOptimalSize(const OutputDevice& rReference)
{
return pReference->LogicToPixel(Size(68 , 112), MapMode(MapUnit::MapAppFont));
return rReference.LogicToPixel(Size(68 , 112), MapMode(MapUnit::MapAppFont));
}
Size getDrawPreviewOptimalSize(const vcl::Window *pReference)
......
......@@ -69,10 +69,6 @@ sw/uiconfig/swriter/ui/indexentry.ui://GtkButton[@id='first'] button-no-label
sw/uiconfig/swriter/ui/indexentry.ui://GtkButton[@id='last'] button-no-label
sw/uiconfig/swriter/ui/inputfielddialog.ui://GtkButton[@id='prev'] button-no-label
sw/uiconfig/swriter/ui/inputfielddialog.ui://GtkButton[@id='next'] button-no-label
sw/uiconfig/swriter/ui/indentpage.ui://GtkLabel[@id='label1'] orphan-label
sw/uiconfig/swriter/ui/indentpage.ui://GtkLabel[@id='label3'] orphan-label
sw/uiconfig/swriter/ui/indentpage.ui://GtkSpinButton[@id='before:0.00cm'] no-labelled-by
sw/uiconfig/swriter/ui/indentpage.ui://GtkSpinButton[@id='after:0.00cm'] no-labelled-by
sw/uiconfig/swriter/ui/insertbookmark.ui://GtkEntry[@id='name'] no-labelled-by
sw/uiconfig/swriter/ui/insertbreak.ui://GtkSpinButton[@id='pagenumsb'] missing-label-for
sw/uiconfig/swriter/ui/insertcaption.ui://GtkEntry[@id='caption_edit'] no-labelled-by
......
......@@ -45,7 +45,7 @@ VCL_BUILDER_FACTORY_ARGS(SvxParaPrevWindow, WB_BORDER)
Size SvxParaPrevWindow::GetOptimalSize() const
{
return getParagraphPreviewOptimalSize(this);
return getParagraphPreviewOptimalSize(*this);
}
void SvxParaPrevWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
......@@ -211,6 +211,194 @@ void SvxParaPrevWindow::DrawParagraph(vcl::RenderContext& rRenderContext)
}
}
ParaPrevWindow::ParaPrevWindow() :
nLeftMargin ( 0 ),
nRightMargin ( 0 ),
nFirstLineOfst ( 0 ),
nUpper ( 0 ),
nLower ( 0 ),
eAdjust ( SvxAdjust::Left ),
eLastLine ( SvxAdjust::Left ),
eLine ( SvxPrevLineSpace::N1 )
{
aSize = Size(11905, 16837);
}
void ParaPrevWindow::SetDrawingArea(weld::DrawingArea* pDrawingArea)
{
Size aOptimalSize(getParagraphPreviewOptimalSize(pDrawingArea->get_ref_device()));
pDrawingArea->set_size_request(aOptimalSize.Width(), aOptimalSize.Height());
CustomWidgetController::SetDrawingArea(pDrawingArea);
}
void ParaPrevWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
{
DrawParagraph(rRenderContext);
}
#define DEF_MARGIN 120
void ParaPrevWindow::DrawParagraph(vcl::RenderContext& rRenderContext)
{
// Count in Twips by default
rRenderContext.Push(PushFlags::MAPMODE);
rRenderContext.SetMapMode(MapMode(MapUnit::MapTwip));
Size aWinSize(GetOutputSizePixel());
aWinSize = rRenderContext.PixelToLogic(aWinSize);
Size aTmp(1, 1);
aTmp = rRenderContext.PixelToLogic(aTmp);
aWinSize.AdjustWidth( -(aTmp.Width() /2) );
aWinSize.AdjustHeight( -(aTmp.Height() /2) );
const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
const Color& rWinColor = rStyleSettings.GetWindowColor();
Color aGrayColor(COL_LIGHTGRAY);
rRenderContext.SetFillColor(rWinColor);
rRenderContext.DrawRect(tools::Rectangle(Point(), aWinSize));
rRenderContext.SetLineColor();
long nH = aWinSize.Height() / 19;
Size aLineSiz(aWinSize.Width() - DEF_MARGIN, nH);
Size aSiz = aLineSiz;
Point aPnt;
aPnt.setX( DEF_MARGIN / 2 );
rRenderContext.SetFillColor(aGrayColor);
for (sal_uInt16 i = 0; i < 9; ++i)
{
if (i == 3)
{
rRenderContext.SetFillColor(COL_GRAY);
auto nTop = nUpper * aLineSiz.Height() / aSize.Height();
aPnt.AdjustY(nTop * 2 );
}
if (i == 6 )
rRenderContext.SetFillColor(aGrayColor);
if (3 <= i && 6 > i)
{
long nLeft = nLeftMargin * aLineSiz.Width() / aSize.Width();
long nFirst = nFirstLineOfst * aLineSiz.Width() / aSize.Width();
long nTmp = nLeft + nFirst;
if (i == 3)
{
aPnt.AdjustX(nTmp );
aSiz.AdjustWidth( -nTmp );
}
else
{
aPnt.AdjustX(nLeft );
aSiz.AdjustWidth( -nLeft );
}
long nRight = nRightMargin * aLineSiz.Width() / aSize.Width();
aSiz.AdjustWidth( -nRight );
}
if (4 == i || 5 == i || 6 == i)
{
switch (eLine)
{
case SvxPrevLineSpace::N1:
break;
case SvxPrevLineSpace::N115:
aPnt.AdjustY(nH / 6.67 ); // 1/.15 = 6.(6)
break;
case SvxPrevLineSpace::N15:
aPnt.AdjustY(nH / 2 );
break;
case SvxPrevLineSpace::N2:
aPnt.AdjustY(nH );
break;
case SvxPrevLineSpace::Prop:
case SvxPrevLineSpace::Min:
case SvxPrevLineSpace::Leading:
break;
}
}
aPnt.AdjustY(nH );
if (3 <= i && 5 >= i)
{
long nLW = long();
switch (i)
{
case 3:
nLW = aLineSiz.Width() * 8 / 10;
break;
case 4:
nLW = aLineSiz.Width() * 9 / 10;
break;
case 5:
nLW = aLineSiz.Width() / 2;
break;
}
if (nLW > aSiz.Width())
nLW = aSiz.Width();
switch (eAdjust)
{
case SvxAdjust::Left:
break;
case SvxAdjust::Right:
aPnt.AdjustX( aSiz.Width() - nLW );
break;
case SvxAdjust::Center:
aPnt.AdjustX(( aSiz.Width() - nLW ) / 2 );
break;
default: ; //prevent warning
}
if (SvxAdjust::Block == eAdjust)
{
if(5 == i)
{
switch( eLastLine )
{
case SvxAdjust::Left:
break;
case SvxAdjust::Right:
aPnt.AdjustX( aSiz.Width() - nLW );
break;
case SvxAdjust::Center:
aPnt.AdjustX(( aSiz.Width() - nLW ) / 2 );
break;
case SvxAdjust::Block:
nLW = aSiz.Width();
break;
default: ; //prevent warning
}
}
else
nLW = aSiz.Width();
}
aSiz.setWidth( nLW );
}
tools::Rectangle aRect(aPnt, aSiz);
rRenderContext.DrawRect( aRect );
Lines[i] = aRect;
if (5 == i)
{
auto nBottom = nLower * aLineSiz.Height() / aSize.Height();
aPnt.AdjustY(nBottom * 2 );
}
aPnt.AdjustY(nH );
// Reset, recalculate for each line
aPnt.setX( DEF_MARGIN / 2 );
aSiz = aLineSiz;
}
rRenderContext.Pop();
}
#undef DEF_MARGIN
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
......@@ -142,7 +142,7 @@ void SwDropCapsPict::SetText( const OUString& rT )
Size SwDropCapsPict::GetOptimalSize() const
{
return getParagraphPreviewOptimalSize(this);
return getParagraphPreviewOptimalSize(*this);
}
void SwDropCapsPict::Resize()
......
......@@ -2109,38 +2109,28 @@ void SwSectionPropertyTabDialog::PageCreated( sal_uInt16 nId, SfxTabPage &rPage
static_cast<SwSectionIndentTabPage&>(rPage).SetWrtShell(rWrtSh);
}
SwSectionIndentTabPage::SwSectionIndentTabPage(vcl::Window *pParent, const SfxItemSet &rAttrSet)
: SfxTabPage(pParent, "IndentPage", "modules/swriter/ui/indentpage.ui", &rAttrSet)
SwSectionIndentTabPage::SwSectionIndentTabPage(TabPageParent pParent, const SfxItemSet &rAttrSet)
: SfxTabPage(pParent, "modules/swriter/ui/indentpage.ui", "IndentPage", &rAttrSet)
, m_xBeforeMF(m_xBuilder->weld_metric_spin_button("before", FUNIT_CM))
, m_xAfterMF(m_xBuilder->weld_metric_spin_button("after", FUNIT_CM))
, m_xPreviewWin(new weld::CustomWeld(*m_xBuilder, "preview", m_aPreviewWin))
{
get(m_pBeforeMF, "before");
get(m_pAfterMF, "after");
get(m_pPreviewWin, "preview");
Link<Edit&,void> aLk = LINK(this, SwSectionIndentTabPage, IndentModifyHdl);
m_pBeforeMF->SetModifyHdl(aLk);
m_pAfterMF->SetModifyHdl(aLk);
Link<weld::MetricSpinButton&,void> aLk = LINK(this, SwSectionIndentTabPage, IndentModifyHdl);
m_xBeforeMF->connect_value_changed(aLk);
m_xAfterMF->connect_value_changed(aLk);
}
SwSectionIndentTabPage::~SwSectionIndentTabPage()
{
disposeOnce();
}
void SwSectionIndentTabPage::dispose()
{
m_pBeforeMF.clear();
m_pAfterMF.clear();
m_pPreviewWin.clear();
SfxTabPage::dispose();
}
bool SwSectionIndentTabPage::FillItemSet( SfxItemSet* rSet)
bool SwSectionIndentTabPage::FillItemSet(SfxItemSet* rSet)
{
if(m_pBeforeMF->IsValueModified() ||
m_pAfterMF->IsValueModified())
if (m_xBeforeMF->get_value_changed_from_saved() || m_xAfterMF->get_value_changed_from_saved())
{
SvxLRSpaceItem aLRSpace(
static_cast< long >(m_pBeforeMF->Denormalize(m_pBeforeMF->GetValue(FUNIT_TWIP))) ,
static_cast< long >(m_pAfterMF->Denormalize(m_pAfterMF->GetValue(FUNIT_TWIP))), 0, 0, RES_LR_SPACE);
m_xBeforeMF->denormalize(m_xBeforeMF->get_value(FUNIT_TWIP)) ,
m_xAfterMF->denormalize(m_xAfterMF->get_value(FUNIT_TWIP)), 0, 0, RES_LR_SPACE);
rSet->Put(aLRSpace);
}
return true;
......@@ -2150,8 +2140,8 @@ void SwSectionIndentTabPage::Reset( const SfxItemSet* rSet)
{
//this page doesn't show up in HTML mode
FieldUnit aMetric = ::GetDfltMetric(false);
SetMetric(*m_pBeforeMF, aMetric);
SetMetric(*m_pAfterMF , aMetric);
SetFieldUnit(*m_xBeforeMF, aMetric);
SetFieldUnit(*m_xAfterMF , aMetric);
SfxItemState eItemState = rSet->GetItemState( RES_LR_SPACE );
if ( eItemState >= SfxItemState::DEFAULT )
......@@ -2159,39 +2149,39 @@ void SwSectionIndentTabPage::Reset( const SfxItemSet* rSet)
const SvxLRSpaceItem& rSpace =
rSet->Get( RES_LR_SPACE );
m_pBeforeMF->SetValue( m_pBeforeMF->Normalize(rSpace.GetLeft()), FUNIT_TWIP );
m_pAfterMF->SetValue( m_pAfterMF->Normalize(rSpace.GetRight()), FUNIT_TWIP );
m_xBeforeMF->set_value(m_xBeforeMF->normalize(rSpace.GetLeft()), FUNIT_TWIP);
m_xAfterMF->set_value(m_xAfterMF->normalize(rSpace.GetRight()), FUNIT_TWIP);
}
else
{
m_pBeforeMF->SetEmptyFieldValue();
m_pAfterMF->SetEmptyFieldValue();
m_xBeforeMF->set_text("");
m_xAfterMF->set_text("");
}
m_pBeforeMF->SaveValue();
m_pAfterMF->SaveValue();
IndentModifyHdl(*m_pBeforeMF);
m_xBeforeMF->save_value();
m_xAfterMF->save_value();
IndentModifyHdl(*m_xBeforeMF);
}
VclPtr<SfxTabPage> SwSectionIndentTabPage::Create( TabPageParent pParent, const SfxItemSet* rAttrSet)
VclPtr<SfxTabPage> SwSectionIndentTabPage::Create(TabPageParent pParent, const SfxItemSet* rAttrSet)
{
return VclPtr<SwSectionIndentTabPage>::Create(pParent.pParent, *rAttrSet);
return VclPtr<SwSectionIndentTabPage>::Create(pParent, *rAttrSet);
}
void SwSectionIndentTabPage::SetWrtShell(SwWrtShell const & rSh)
{
//set sensible values at the preview
m_pPreviewWin->SetAdjust(SvxAdjust::Block);
m_pPreviewWin->SetLastLine(SvxAdjust::Block);
m_aPreviewWin.SetAdjust(SvxAdjust::Block);
m_aPreviewWin.SetLastLine(SvxAdjust::Block);
const SwRect& rPageRect = rSh.GetAnyCurRect( CurRectType::Page );
Size aPageSize(rPageRect.Width(), rPageRect.Height());
m_pPreviewWin->SetSize(aPageSize);
m_aPreviewWin.SetSize(aPageSize);
}
IMPL_LINK_NOARG(SwSectionIndentTabPage, IndentModifyHdl, Edit&, void)
IMPL_LINK_NOARG(SwSectionIndentTabPage, IndentModifyHdl, weld::MetricSpinButton&, void)
{
m_pPreviewWin->SetLeftMargin( static_cast< long >(m_pBeforeMF->Denormalize(m_pBeforeMF->GetValue(FUNIT_TWIP))) );
m_pPreviewWin->SetRightMargin( static_cast< long >(m_pAfterMF->Denormalize(m_pAfterMF->GetValue(FUNIT_TWIP))) );
m_pPreviewWin->Invalidate();
m_aPreviewWin.SetLeftMargin(m_xBeforeMF->denormalize(m_xBeforeMF->get_value(FUNIT_TWIP)));
m_aPreviewWin.SetRightMargin(m_xAfterMF->denormalize(m_xAfterMF->get_value(FUNIT_TWIP)));
m_aPreviewWin.Invalidate();
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
......@@ -228,21 +228,20 @@ public:
class SwSectionIndentTabPage : public SfxTabPage
{
VclPtr<MetricField> m_pBeforeMF;
VclPtr<MetricField> m_pAfterMF;
VclPtr<SvxParaPrevWindow> m_pPreviewWin;
ParaPrevWindow m_aPreviewWin;
std::unique_ptr<weld::MetricSpinButton> m_xBeforeMF;
std::unique_ptr<weld::MetricSpinButton> m_xAfterMF;
std::unique_ptr<weld::CustomWeld> m_xPreviewWin;
DECL_LINK(IndentModifyHdl, Edit&, void);
DECL_LINK(IndentModifyHdl, weld::MetricSpinButton&, void);
public:
SwSectionIndentTabPage( vcl::Window *pParent, const SfxItemSet &rAttrSet );
SwSectionIndentTabPage(TabPageParent pParent, const SfxItemSet &rAttrSet);
virtual ~SwSectionIndentTabPage() override;
virtual void dispose() override;
virtual bool FillItemSet( SfxItemSet* ) override;
virtual void Reset( const SfxItemSet* ) override;
static VclPtr<SfxTabPage> Create( TabPageParent pParent,
const SfxItemSet* rAttrSet);
static VclPtr<SfxTabPage> Create(TabPageParent pParent, const SfxItemSet* rAttrSet);
void SetWrtShell(SwWrtShell const & rSh);
};
......
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface domain="sw">
<!-- interface-requires gtk+ 3.0 -->
<!-- interface-requires LibreOffice 1.0 -->
<requires lib="gtk+" version="3.18"/>
<object class="GtkAdjustment" id="adjustment1">
<property name="lower">-99.989999999999995</property>
<property name="upper">99.989999999999995</property>
<property name="step_increment">0.10000000000000001</property>
<property name="page_increment">1</property>
</object>
<object class="GtkAdjustment" id="adjustment2">
<property name="lower">-99.989999999999995</property>
<property name="upper">99.989999999999995</property>
<property name="step_increment">0.10000000000000001</property>
<property name="page_increment">1</property>
</object>
<object class="GtkGrid" id="IndentPage">
<property name="visible">True</property>
<property name="can_focus">False</property>
......@@ -48,58 +54,54 @@
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes" context="indentpage|label1">_Before section</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">before</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes" context="indentpage|label3">_After section</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">after</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="before:0.00cm">
<object class="GtkSpinButton" id="before">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="activates_default">True</property>
<property name="adjustment">adjustment1</property>
<property name="digits">2</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="after:0.00cm">
<object class="GtkSpinButton" id="after">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="adjustment">adjustment1</property>
<property name="activates_default">True</property>
<property name="adjustment">adjustment2</property>
<property name="digits">2</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
</object>
......@@ -120,8 +122,6 @@
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
<child>
......@@ -132,14 +132,31 @@
<property name="vexpand">True</property>
<property name="top_padding">24</property>
<child>
<object class="svxlo-SvxParaPrevWindow" id="preview">
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="can_focus">True</property>
<property name="halign">center</property>
<property name="valign">start</property>
<child internal-child="accessible">
<object class="AtkObject" id="preview-atkobject">
<property name="AtkObject::accessible-name" translatable="yes" context="indentpage|preview-atkobject">Example</property>
<property name="hscrollbar_policy">never</property>
<property name="vscrollbar_policy">never</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkViewport">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkDrawingArea" id="preview">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="valign">start</property>
<child internal-child="accessible">
<object class="AtkObject" id="preview-atkobject">
<property name="AtkObject::accessible-name" translatable="yes" context="indentpage|preview-atkobject">Example</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
......@@ -148,16 +165,12 @@
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">1</property>
<property name="height">1</property>
</packing>
</child>
</object>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment