///<summary>Double click on appt sheet or on a single appointment.</summary>
		private void ContrApptSheet2_DoubleClick(object sender,System.EventArgs e) {
			mouseIsDown=false;
			//this logic is a little different than mouse down for now because on the first click of a 
			//double click, an appointment control is created under the mouse.
			if(ContrApptSingle.ClickedAptNum!=0) {//on appt
				long patnum=PIn.Long(TempApptSingle.DataRoww["PatNum"].ToString());
				TempApptSingle.Dispose();
				if(Appointments.GetOneApt(ContrApptSingle.ClickedAptNum)==null) {
					MsgBox.Show(this,"Selected appointment no longer exists.");
					RefreshModuleDataPeriod();
					RefreshModuleScreenPeriod();
					return;
				}
				//security handled inside the form
				FormApptEdit FormAE=new FormApptEdit(ContrApptSingle.ClickedAptNum);
				FormAE.ShowDialog();
				if(FormAE.DialogResult==DialogResult.OK) {
					Appointment apt=Appointments.GetOneApt(ContrApptSingle.ClickedAptNum);
					if(apt!=null && DoesOverlap(apt)) {
						Appointment aptOld=apt.Clone();
						MsgBox.Show(this,"Appointment is too long and would overlap another appointment.  Automatically shortened to fit.");
						while(DoesOverlap(apt)) {
							apt.Pattern=apt.Pattern.Substring(0,apt.Pattern.Length-1);
							if(apt.Pattern.Length==1) {
								break;
							}
						}
						try {
							Appointments.Update(apt,aptOld);
						}
						catch(ApplicationException ex) {
							MessageBox.Show(ex.Message);
						}
					}
					ModuleSelected(patnum);//apt.PatNum);//apt might be null if user deleted appt.
					SetInvalid();
				}
			}
			//not on apt, so trying to schedule an appointment---------------------------------------------------------------------
			else {
				if(!Security.IsAuthorized(Permissions.AppointmentCreate)) {
					return;
				}
				FormPatientSelect FormPS=new FormPatientSelect();
				if(PatCur!=null) {
					FormPS.InitialPatNum=PatCur.PatNum;
				}
				FormPS.ShowDialog();
				if(FormPS.DialogResult!=DialogResult.OK) {
					return;
				}
				if(PatCur==null || FormPS.SelectedPatNum!=PatCur.PatNum) {//if the patient was changed
					RefreshModuleDataPatient(FormPS.SelectedPatNum);
					OnPatientSelected(PatCur);
					//RefreshModulePatient(FormPS.SelectedPatNum);
				}
				Appointment apt;
				if(FormPS.NewPatientAdded) {
					//Patient pat=Patients.GetPat(PatCurNum);
					apt=new Appointment();
					apt.PatNum=PatCur.PatNum;
					apt.IsNewPatient=true;
					apt.Pattern="/X/";
					if(PatCur.PriProv==0) {
						apt.ProvNum=PrefC.GetLong(PrefName.PracticeDefaultProv);
					}
					else {
						apt.ProvNum=PatCur.PriProv;
					}
					apt.ProvHyg=PatCur.SecProv;
					apt.AptStatus=ApptStatus.Scheduled;
					DateTime d=AppointmentL.DateSelected;
					if(ApptDrawing.IsWeeklyView) {
						d=WeekStartDate.AddDays(SheetClickedonDay);
					}
					//minutes always rounded down.
					int minutes=(int)(ContrAppt.SheetClickedonMin/ApptDrawing.MinPerIncr)*ApptDrawing.MinPerIncr;
					apt.AptDateTime=new DateTime(d.Year,d.Month,d.Day,ContrAppt.SheetClickedonHour,minutes,0);
					if(PatCur.AskToArriveEarly>0) {
						apt.DateTimeAskedToArrive=apt.AptDateTime.AddMinutes(-PatCur.AskToArriveEarly);
						MessageBox.Show(Lan.g(this,"Ask patient to arrive")+" "+PatCur.AskToArriveEarly
							+" "+Lan.g(this,"minutes early at")+" "+apt.DateTimeAskedToArrive.ToShortTimeString()+".");
					}
					apt.Op=SheetClickedonOp;
					Operatory curOp=Operatories.GetOperatory(apt.Op);
					//New patient. Set to prospective if operatory is set to set prospective.
					if(curOp.SetProspective) {
						if(MsgBox.Show(this,MsgBoxButtons.OKCancel,"Patient's status will be set to Prospective.")) {
							Patient patOld=PatCur.Copy();
							PatCur.PatStatus=PatientStatus.Prospective;
							Patients.Update(PatCur,patOld);
						}
					}
					//if(curOp.ProvDentist!=0) {//if no dentist is assigned to op, then keep the original dentist.  All appts must have prov.
					//  apt.ProvNum=curOp.ProvDentist;
					//}
					//apt.ProvHyg=curOp.ProvHygienist;
					long assignedDent=Schedules.GetAssignedProvNumForSpot(SchedListPeriod,curOp,false,apt.AptDateTime);
					long assignedHyg=Schedules.GetAssignedProvNumForSpot(SchedListPeriod,curOp,true,apt.AptDateTime);
					if(assignedDent!=0) {//if no dentist is assigned to op, then keep the original dentist.  All appts must have prov.
					  apt.ProvNum=assignedDent;
					}
					apt.ProvHyg=assignedHyg;
					apt.IsHygiene=curOp.IsHygiene;
					apt.TimeLocked=PrefC.GetBool(PrefName.AppointmentTimeIsLocked);
					if(curOp.ClinicNum==0){
						apt.ClinicNum=PatCur.ClinicNum;
					}
					else{
						apt.ClinicNum=curOp.ClinicNum;
					}
					try {
						Appointments.Insert(apt);
					}
					catch(ApplicationException ex) {
						MessageBox.Show(ex.Message);
					}
					FormApptEdit FormAE=new FormApptEdit(apt.AptNum);//this is where security log entry is made
					FormAE.IsNew=true;
					FormAE.ShowDialog();
					if(apt.IsNewPatient) {
						AutomationL.Trigger(AutomationTrigger.CreateApptNewPat,null,apt.PatNum);
					}
					if(FormAE.DialogResult==DialogResult.OK) {
						RefreshModuleDataPatient(PatCur.PatNum);
						OnPatientSelected(PatCur);
						//RefreshModulePatient(PatCurNum);
						if(apt!=null && DoesOverlap(apt)) {
							Appointment aptOld=apt.Clone();
							MsgBox.Show(this,"Appointment is too long and would overlap another appointment.  Automatically shortened to fit.");
							while(DoesOverlap(apt)) {
								apt.Pattern=apt.Pattern.Substring(0,apt.Pattern.Length-1);
								if(apt.Pattern.Length==1) {
									break;
								}
							}
							try {
								Appointments.Update(apt,aptOld);
							}
							catch(ApplicationException ex) {
								MessageBox.Show(ex.Message);
							}
						}
						RefreshPeriod();
						SetInvalid();
					}
				}
				else {//new patient not added
					if(Appointments.HasPlannedEtc(PatCur.PatNum) | (Plugins.HookMethod(this,"ContrAppt.ContrApptSheet2_DoubleClick_apptOtherShow"))) {
						DisplayOtherDlg(true);
					}
					else {
						FormApptsOther FormAO=new FormApptsOther(PatCur.PatNum);//doesn't actually get shown
						CheckStatus();
						FormAO.InitialClick=true;
						FormAO.MakeAppointment();
						//if(FormAO.OResult==OtherResult.Cancel) {//this wasn't catching user hitting cancel from within appt edit window
						//	return;
						//}
						if(FormAO.AptNumsSelected.Count>0) {
							ContrApptSingle.SelectedAptNum=FormAO.AptNumsSelected[0];
						}
						//RefreshModuleDataPatient(FormAO.SelectedPatNum);//patient won't have changed
						//OnPatientSelected(PatCur.PatNum,PatCur.GetNameLF(),PatCur.Email!="",PatCur.ChartNumber);
						apt=Appointments.GetOneApt(ContrApptSingle.SelectedAptNum);
						if(apt!=null && DoesOverlap(apt)) {
							Appointment aptOld=apt.Clone();
							MsgBox.Show(this,"Appointment is too long and would overlap another appointment.  Automatically shortened to fit.");
							while(DoesOverlap(apt)) {
								apt.Pattern=apt.Pattern.Substring(0,apt.Pattern.Length-1);
								if(apt.Pattern.Length==1) {
									break;
								}
							}
							try {
								Appointments.Update(apt,aptOld);
							}
							catch(ApplicationException ex) {
								MessageBox.Show(ex.Message);
							}
						}
						RefreshPeriod();
						SetInvalid();
					}
				}
			}
		}
		///<summary></summary>
		public FormApptEdit(long aptNum)
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();
			Lan.F(this);
			DS=Appointments.GetApptEdit(aptNum);
			AptCur=Appointments.TableToObject(DS.Tables["Appointment"]);
			AptOld=AptCur.Clone();
		}
		private void butNew_Click(object sender,EventArgs e) {
			/*if(ApptPlanned.Visible){
				if(MessageBox.Show(Lan.g(this,"Replace existing planned appointment?")
					,"",MessageBoxButtons.OKCancel)!=DialogResult.OK)
					return;
				//Procedures.UnattachProcsInPlannedAppt(ApptPlanned.Info.MyApt.AptNum);
				AppointmentL.Delete(PIn.PInt(ApptPlanned.DataRoww["AptNum"].ToString()));
			}*/
			Appointment AptCur=new Appointment();
			AptCur.PatNum=PatCur.PatNum;
			AptCur.ProvNum=PatCur.PriProv;
			AptCur.ClinicNum=PatCur.ClinicNum;
			AptCur.AptStatus=ApptStatus.Planned;
			AptCur.AptDateTime=DateTimeOD.Today;
			AptCur.Pattern="/X/";
			AptCur.TimeLocked=PrefC.GetBool(PrefName.AppointmentTimeIsLocked);
			Appointments.Insert(AptCur);
			PlannedAppt plannedAppt=new PlannedAppt();
			plannedAppt.AptNum=AptCur.AptNum;
			plannedAppt.PatNum=PatCur.PatNum;
			plannedAppt.ItemOrder=TablePlanned.Rows.Count+1;
			PlannedAppts.Insert(plannedAppt);
			FormApptEdit FormApptEdit2=new FormApptEdit(AptCur.AptNum);
			FormApptEdit2.IsNew=true;
			FormApptEdit2.ShowDialog();
			if(FormApptEdit2.DialogResult!=DialogResult.OK){
				//delete new appt, delete plannedappt, and unattach procs already handled in dialog
				Refresh();
				return;
			}
			List<Procedure> myProcList=Procedures.Refresh(PatCur.PatNum);
			bool allProcsHyg=true;
			for(int i=0;i<myProcList.Count;i++){
				if(myProcList[i].PlannedAptNum!=AptCur.AptNum)
					continue;//only concerned with procs on this plannedAppt
				if(!ProcedureCodes.GetProcCode(myProcList[i].CodeNum).IsHygiene){
					allProcsHyg=false;
					break;
				}
			}
			if(allProcsHyg && PatCur.SecProv!=0){
				Appointment aptOld=AptCur.Clone();
				AptCur.ProvNum=PatCur.SecProv;
				Appointments.Update(AptCur,aptOld);
			}
			Patient patOld=PatCur.Copy();
			//PatCur.NextAptNum=AptCur.AptNum;
			PatCur.PlannedIsDone=false;
			Patients.Update(PatCur,patOld);
			Refresh();//if procs were added in appt, then this will display them
		}