LLGroupNotifyBox::LLGroupNotifyBox(const std::string& subject,
								   const std::string& message,
								   const std::string& from_name,
								   const LLUUID& group_id,
								   const LLUUID& group_insignia,
								   const std::string& group_name,
								   const U32& t,
								   const bool& has_inventory,
								   const std::string& inventory_name,
								   LLOfferInfo* inventory_offer)
:	LLPanel(std::string("groupnotify"), LLGroupNotifyBox::getGroupNotifyRect(), BORDER_YES),
	mAnimating(TRUE),
	mTimer(),
	mGroupID(group_id),
	mHasInventory(has_inventory),
	mInventoryOffer(inventory_offer)
{
	setFocusRoot(TRUE);

	time_t timestamp = (time_t)t;

	std::string time_buf = g_formatted_time(timestamp);

	setFollows(FOLLOWS_TOP|FOLLOWS_RIGHT);
	setBackgroundVisible(TRUE);
	setBackgroundOpaque(TRUE);

	// TODO: add a color for group notices
	setBackgroundColor( gColors.getColor("GroupNotifyBoxColor") );

	LLIconCtrl* icon;
	LLTextEditor* text;

	const S32 VPAD = 2;
	const S32 TOP = getRect().getHeight() - 32; // Get past the top menu bar
	const S32 BOTTOM_PAD = VPAD * 2;
	const S32 BTN_TOP = BOTTOM_PAD + BTN_HEIGHT + VPAD;
	const S32 RIGHT = getRect().getWidth() - HPAD - HPAD;
	const S32 LINE_HEIGHT = 16;

	const S32 LABEL_WIDTH = 64;
	const S32 ICON_WIDTH = 64;

	S32 y = TOP;
	S32 x = HPAD + HPAD;

	class NoticeText : public LLTextBox
	{
	public:
		NoticeText(const std::string& name, const LLRect& rect, const std::string& text = LLStringUtil::null, const LLFontGL* font = NULL) 
			: LLTextBox(name, rect, text, font)
		{
			setHAlign(LLFontGL::RIGHT);
			setFontStyle(LLFontGL::DROP_SHADOW_SOFT);
			setBorderVisible(FALSE);
			setColor( gColors.getColor("GroupNotifyTextColor") );
			setBackgroundColor( gColors.getColor("GroupNotifyBoxColor") );
		}
	};


	// Title
	addChild(new NoticeText(std::string("title"),LLRect(x,y,RIGHT - HPAD,y - LINE_HEIGHT),std::string("Group Notice"),LLFontGL::sSansSerifHuge));

	y -= llfloor(1.5f*LINE_HEIGHT);

	x += HPAD + HPAD + ICON_WIDTH;

	std::stringstream from;
	from << "Sent by " << from_name << ", " << group_name;

	addChild(new NoticeText(std::string("group"),LLRect(x,y,RIGHT - HPAD,y - LINE_HEIGHT),from.str(),LLFontGL::sSansSerif));
	
	y -= (LINE_HEIGHT + VPAD);
	x = HPAD + HPAD;

	// TODO: change this to be the group icon.
	if (!group_insignia.isNull())
	{
		icon = new LLIconCtrl(std::string("icon"),
							  LLRect(x, y, x+ICON_WIDTH, y-ICON_WIDTH),
							  group_insignia);
	}
	else
	{
		icon = new LLIconCtrl(std::string("icon"),
							  LLRect(x, y, x+ICON_WIDTH, y-ICON_WIDTH),
							  std::string("notify_box_icon.tga"));
	}

	icon->setMouseOpaque(FALSE);
	addChild(icon);

	x += HPAD + HPAD + ICON_WIDTH;
	// If we have inventory with this message, leave room for the name.
	S32 box_bottom = BTN_TOP + (mHasInventory ? (LINE_HEIGHT + 2*VPAD) : 0);

	text = new LLViewerTextEditor(std::string("box"),
		LLRect(x, y, RIGHT, box_bottom),
		DB_GROUP_NOTICE_MSG_STR_LEN,
		LLStringUtil::null,
		LLFontGL::sSansSerif,
		FALSE);

	static const LLStyleSP headerstyle(new LLStyle(true,LLColor4::black,"SansSerifBig"));
	static const LLStyleSP datestyle(new LLStyle(true,LLColor4::black,"serif"));

	text->appendStyledText(subject,false,false,&headerstyle);
	text->appendStyledText(time_buf,false,false,&datestyle);
	// Sadly, our LLTextEditor can't handle both styled and unstyled text
	// at the same time.  Hence this space must be styled. JC
	text->appendColoredText(std::string(" "),false,false,LLColor4::grey4);
	text->appendColoredText(message,false,false,LLColor4::grey4);

	LLColor4 semi_transparent(1.0f,1.0f,1.0f,0.8f);
	text->setCursor(0,0);
	text->setEnabled(FALSE);
	text->setWordWrap(TRUE);
	//text->setTabStop(FALSE); // was interfering with copy-and-paste
	text->setTabsToNextField(TRUE);
	text->setMouseOpaque(TRUE);
	text->setBorderVisible(TRUE);
	text->setTakesNonScrollClicks(TRUE);
	text->setHideScrollbarForShortDocs(TRUE);
	text->setReadOnlyBgColor ( semi_transparent );
	text->setWriteableBgColor ( semi_transparent );
	
	addChild(text);

	y = box_bottom - VPAD;

	if (mHasInventory)
	{
			addChild(new NoticeText(std::string("subjecttitle"),LLRect(x,y,x + LABEL_WIDTH,y - LINE_HEIGHT),std::string("Attached: "),LLFontGL::sSansSerif));

			LLUIImagePtr item_icon = get_item_icon(mInventoryOffer->mType,
													LLInventoryType::IT_TEXTURE,
													0, FALSE);


			x += LABEL_WIDTH + HPAD;

			std::stringstream ss;
			ss << "        " << inventory_name;
			LLTextBox *line = new LLTextBox(std::string("object_name"),LLRect(x,y,RIGHT - HPAD,y - LINE_HEIGHT),ss.str(),LLFontGL::sSansSerif);
			line->setEnabled(FALSE);
			line->setBorderVisible(TRUE);
			line->setDisabledColor(LLColor4::blue4);
			line->setFontStyle(LLFontGL::NORMAL);
			line->setBackgroundVisible(true);
			line->setBackgroundColor( semi_transparent );
			addChild(line);

			icon = new LLIconCtrl(std::string("icon"),
									LLRect(x, y, x+16, y-16),
									item_icon->getName());
			icon->setMouseOpaque(FALSE);
			addChild(icon);
	}

	LLButton* btn;
	btn = new LLButton(std::string("next"),
				LLRect(getRect().getWidth()-26, BOTTOM_PAD + 20, getRect().getWidth()-2, BOTTOM_PAD),
				std::string("notify_next.png"),
				std::string("notify_next.png"),
				LLStringUtil::null,
				onClickNext,
				this,
				LLFontGL::sSansSerif);
	btn->setToolTip(std::string("Next")); // *TODO: Translate
	btn->setScaleImage(TRUE);
	addChild(btn);
	mNextBtn = btn;

	S32 btn_width = 80;
	S32 wide_btn_width = 120;
	LLRect btn_rect;
	x = 3 * HPAD;

	btn_rect.setOriginAndSize(x,
								BOTTOM_PAD,
								btn_width,
								BTN_HEIGHT);

	btn = new LLButton(std::string("OK"), btn_rect, LLStringUtil::null, onClickOk, this);
	addChild(btn, -1);
	setDefaultBtn(btn);

	x += btn_width + HPAD;

	
	btn_rect.setOriginAndSize(x,
								BOTTOM_PAD,
								wide_btn_width,
								BTN_HEIGHT);

	btn = new LLButton(std::string("Group Notices"), btn_rect, LLStringUtil::null, onClickGroupInfo, this);
	btn->setToolTip(std::string("View past notices or opt-out of receiving these messages here.")); // TODO: Translate
	addChild(btn, -1);

	if (mHasInventory && mInventoryOffer)
	{
		x += wide_btn_width + HPAD;

		btn_rect.setOriginAndSize(x,
									BOTTOM_PAD,
									wide_btn_width,
									BTN_HEIGHT);

		std::string btn_lbl("");
		if(is_openable(mInventoryOffer->mType))
		{
			btn_lbl = "Open Attachment";
		}
		else
		{
			btn_lbl = "Save Attachment";
		}
		mSaveInventoryBtn = new LLButton(btn_lbl, btn_rect, LLStringUtil::null, onClickSaveInventory, this);
		mSaveInventoryBtn->setVisible(mHasInventory);
		addChild(mSaveInventoryBtn);
	}

	sGroupNotifyBoxCount++;

	// If this is the only notify box, don't show the next button
	if (sGroupNotifyBoxCount == 1)
	{
		mNextBtn->setVisible(FALSE);
	}
}
BOOL LLPreviewGesture::postBuild()
{
	LLLineEditor* edit;
	LLComboBox* combo;
	LLButton* btn;
	LLScrollListCtrl* list;
	LLTextBox* text;
	LLCheckBoxCtrl* check;

	edit = LLViewerUICtrlFactory::getLineEditorByName(this, "trigger_editor");
	edit->setKeystrokeCallback(onKeystrokeCommit);
	edit->setCommitCallback(onCommitSetDirty);
	edit->setCommitOnFocusLost(TRUE);
	edit->setCallbackUserData(this);
	edit->setIgnoreTab(TRUE);
	mTriggerEditor = edit;

	text = LLViewerUICtrlFactory::getTextBoxByName(this, "replace_text");
	text->setEnabled(FALSE);
	mReplaceText = text;

	edit = LLViewerUICtrlFactory::getLineEditorByName(this, "replace_editor");
	edit->setEnabled(FALSE);
	edit->setKeystrokeCallback(onKeystrokeCommit);
	edit->setCommitCallback(onCommitSetDirty);
	edit->setCommitOnFocusLost(TRUE);
	edit->setCallbackUserData(this);
	edit->setIgnoreTab(TRUE);
	mReplaceEditor = edit;

	combo = LLViewerUICtrlFactory::getComboBoxByName(this, "modifier_combo");
	combo->setCommitCallback(onCommitSetDirty);
	combo->setCallbackUserData(this);
	mModifierCombo = combo;

	combo = LLViewerUICtrlFactory::getComboBoxByName(this, "key_combo");
	combo->setCommitCallback(onCommitSetDirty);
	combo->setCallbackUserData(this);
	mKeyCombo = combo;

	list = LLViewerUICtrlFactory::getScrollListByName(this, "library_list");
	list->setCommitCallback(onCommitLibrary);
	list->setDoubleClickCallback(onClickAdd);
	list->setCallbackUserData(this);
	mLibraryList = list;

	btn = LLViewerUICtrlFactory::getButtonByName(this, "add_btn");
	btn->setClickedCallback(onClickAdd);
	btn->setCallbackUserData(this);
	btn->setEnabled(FALSE);
	mAddBtn = btn;

	btn = LLViewerUICtrlFactory::getButtonByName(this, "up_btn");
	btn->setClickedCallback(onClickUp);
	btn->setCallbackUserData(this);
	btn->setEnabled(FALSE);
	mUpBtn = btn;

	btn = LLViewerUICtrlFactory::getButtonByName(this, "down_btn");
	btn->setClickedCallback(onClickDown);
	btn->setCallbackUserData(this);
	btn->setEnabled(FALSE);
	mDownBtn = btn;

	btn = LLViewerUICtrlFactory::getButtonByName(this, "delete_btn");
	btn->setClickedCallback(onClickDelete);
	btn->setCallbackUserData(this);
	btn->setEnabled(FALSE);
	mDeleteBtn = btn;

	list = LLViewerUICtrlFactory::getScrollListByName(this, "step_list");
	list->setCommitCallback(onCommitStep);
	list->setCallbackUserData(this);
	mStepList = list;

	// Options
	text = LLViewerUICtrlFactory::getTextBoxByName(this, "options_text");
	text->setBorderVisible(TRUE);
	mOptionsText = text;

	combo = LLViewerUICtrlFactory::getComboBoxByName(this, "animation_list");
	combo->setVisible(FALSE);
	combo->setCommitCallback(onCommitAnimation);
	combo->setCallbackUserData(this);
	mAnimationCombo = combo;

	LLRadioGroup* group;
	group = LLViewerUICtrlFactory::getRadioGroupByName(this, "animation_trigger_type");
	group->setVisible(FALSE);
	group->setCommitCallback(onCommitAnimationTrigger);
	group->setCallbackUserData(this);
	mAnimationRadio = group;

	combo = LLViewerUICtrlFactory::getComboBoxByName(this, "sound_list");
	combo->setVisible(FALSE);
	combo->setCommitCallback(onCommitSound);
	combo->setCallbackUserData(this);
	mSoundCombo = combo;

	edit = LLViewerUICtrlFactory::getLineEditorByName(this, "chat_editor");
	edit->setVisible(FALSE);
	edit->setCommitCallback(onCommitChat);
	//edit->setKeystrokeCallback(onKeystrokeCommit);
	edit->setCommitOnFocusLost(TRUE);
	edit->setCallbackUserData(this);
	edit->setIgnoreTab(TRUE);
	mChatEditor = edit;

	check = LLViewerUICtrlFactory::getCheckBoxByName(this, "wait_anim_check");
	check->setVisible(FALSE);
	check->setCommitCallback(onCommitWait);
	check->setCallbackUserData(this);
	mWaitAnimCheck = check;

	check = LLViewerUICtrlFactory::getCheckBoxByName(this, "wait_time_check");
	check->setVisible(FALSE);
	check->setCommitCallback(onCommitWait);
	check->setCallbackUserData(this);
	mWaitTimeCheck = check;

	edit = LLViewerUICtrlFactory::getLineEditorByName(this, "wait_time_editor");
	edit->setEnabled(FALSE);
	edit->setVisible(FALSE);
	edit->setPrevalidate(LLLineEditor::prevalidateFloat);
//	edit->setKeystrokeCallback(onKeystrokeCommit);
	edit->setCommitOnFocusLost(TRUE);
	edit->setCommitCallback(onCommitWaitTime);
	edit->setCallbackUserData(this);
	edit->setIgnoreTab(TRUE);
	mWaitTimeEditor = edit;

	// Buttons at the bottom
	check = LLViewerUICtrlFactory::getCheckBoxByName(this, "active_check");
	check->setCommitCallback(onCommitActive);
	check->setCallbackUserData(this);
	mActiveCheck = check;

	btn = LLViewerUICtrlFactory::getButtonByName(this, "save_btn");
	btn->setClickedCallback(onClickSave);
	btn->setCallbackUserData(this);
	mSaveBtn = btn;

	btn = LLViewerUICtrlFactory::getButtonByName(this, "preview_btn");
	btn->setClickedCallback(onClickPreview);
	btn->setCallbackUserData(this);
	mPreviewBtn = btn;


	// Populate the comboboxes
	addModifiers();
	addKeys();
	addAnimations();
	addSounds();


	const LLInventoryItem* item = getItem();

	if (item) 
	{
		childSetCommitCallback("desc", LLPreview::onText, this);
		childSetText("desc", item->getDescription());
		childSetPrevalidate("desc", &LLLineEditor::prevalidatePrintableNotPipe);
	}

	return TRUE;
}