00001 using System;
00002 using System.Collections;
00003 using System.Collections.Generic;
00004 using Gtk;
00005 using Foodolini.BusinessLogic;
00006 using Foodolini.Activities;
00007 using System.Text;
00008 using Foodolini.Activities.Ingredients;
00009
00010 namespace Foodolini.Activities.ShoppingList
00011 {
00012 [FoodoliniActivity("Shopping shoppingList", true)]
00013 [System.ComponentModel.ToolboxItem(true)]
00014 public partial class ShoppingListActivity : Gtk.Bin, IActivity
00015 {
00016 private NodeStore shoppingListStore;
00017 private Foodolini.BusinessLogic.ShoppingList shoppingList;
00018 private Person currentUser;
00019
00020 public ShoppingListActivity()
00021 {
00022 this.Build();
00023 }
00024
00025 public Widget Widget
00026 {
00027 get { return this; }
00028 }
00029
00030 private IOwner owner;
00031
00032 public void Register(IOwner owner)
00033 {
00034 this.owner = owner;
00035 this.owner.CurrentUserChanged += OwnerhandleCurrentUserChanged;
00036
00037 CellRendererSpin quantityCell = new CellRendererSpin();
00038 quantityCell.Editable=true;
00039 quantityCell.Adjustment=new Adjustment(0,0,100000, 50, 50, 50);
00040 quantityCell.Digits = 0;
00041 this.shoppingListViewer.AppendColumn("Quantity (g)",
00042 quantityCell, (column, cell, node) =>
00043 {
00044 ((CellRendererSpin)cell).Text = ((ShoppingListItemAdapter)node).Quantity.ToString ("0");
00045 });
00046
00047 quantityCell.Edited += delegate(object o, EditedArgs args) {
00048 var node = (ShoppingListItemAdapter)shoppingListStore.GetNode(new TreePath(args.Path));
00049 double newValue;
00050 if(double.TryParse(args.NewText, out newValue)) {
00051 node.Quantity = newValue;
00052
00053 this.shoppingList.Save();
00054 }
00055 };
00056
00057 this.shoppingListViewer.AppendColumn("Ingredient", new CellRendererText(), "text", 1);
00058
00059 }
00060
00061 void OwnerhandleCurrentUserChanged(object sender, PersonEventArgs e)
00062 {
00063 this.shoppingListViewer.NodeStore = null;
00064 currentUser = e.Person;
00065 btnAddIngredient.Sensitive =
00066 btnClear.Sensitive =
00067 btnPrint.Sensitive = (currentUser != null);
00068
00069 if (currentUser != null)
00070 LoadShoppingListData();
00071 }
00072
00077 private void LoadShoppingListData()
00078 {
00079 shoppingListStore = new NodeStore(typeof(ShoppingListItemAdapter));
00080 shoppingList = new Foodolini.BusinessLogic.ShoppingList(currentUser);
00081
00082 foreach (var item in shoppingList.GetShoppingListItems())
00083 this.shoppingListStore.AddNode(new ShoppingListItemAdapter(item));
00084
00085 this.shoppingListViewer.NodeStore = shoppingListStore;
00086 this.shoppingListViewer.QueueResize();
00087 }
00088
00089 public void Unregister()
00090 {
00091 this.owner.CurrentUserChanged -= OwnerhandleCurrentUserChanged;
00092 this.owner = null;
00093 }
00094
00095 protected virtual void OnBtnClearActivated(object sender, System.EventArgs e)
00096 {
00097 shoppingList.Clear();
00098 LoadShoppingListData();
00099 }
00100
00101 protected virtual void OnBtnAddIngredientClicked(object sender, System.EventArgs e)
00102 {
00103 IngredientSelector dialog = new IngredientSelector(true);
00104 if (dialog.Run() == (int)ResponseType.Ok) {
00105 double qty = dialog.Quantity;
00106 Ingredient ingredient = dialog.SelectedIngredient;
00107 this.shoppingList.AddIngredient(ingredient, qty);
00108 this.shoppingList.Save();
00109 LoadShoppingListData();
00110 }
00111 dialog.Destroy();
00112 SetDeleteButtonState();
00113 }
00114
00122 public void AddRecipe(Recipe recipe, double servings){
00123 if(this.owner.CurrentUser == null)
00124 throw new Exception("Cannot add an ingredient to shopping list when no user is selected!");
00125 this.shoppingList.AddRecipe(recipe, servings);
00126 this.shoppingList.Save();
00127 LoadShoppingListData();
00128 }
00129
00135 protected virtual void OnBtnPrintClicked(object sender, System.EventArgs e)
00136 {
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 StringBuilder sb = new StringBuilder();
00166
00167 foreach (ShoppingListItemAdapter item in this.shoppingListStore) {
00168 sb.Append(string.Format("{0,10} {1} ", item.Quantity, "g"));
00169 sb.Append(string.Format("{0,20}", item.Ingredient));
00170 if (!string.IsNullOrEmpty(item.Recipe)) {
00171 sb.Append("\t(" + item.Recipe + ")");
00172 }
00173 sb.Append("\n");
00174 }
00175
00176
00177 double qWidth = 0, dWidth;
00178
00179
00180 Pango.Layout headline = null;
00181
00182
00183 PrintOperation p = new PrintOperation();
00184
00185 p.Paginate += delegate(object o, PaginateArgs args) {
00186
00187 foreach(ShoppingListItemAdapter item in this.shoppingListStore){
00188 var w = item.SetupLayout(args.Context);
00189 qWidth = Math.Max(qWidth, w);
00190 }
00191
00192
00193 double docWidth = args.Context.Width;
00194 qWidth = Math.Min(qWidth, docWidth / 2);
00195 dWidth = docWidth - qWidth - 20 - 20;
00196
00197
00198 headline = args.Context.CreatePangoLayout();
00199 headline.SetMarkup("<span size='xx-large' face='DejaVu Sans'>Shopping list, " + DateTime.Now.ToString("d") + "</span>");
00200
00201 int hw, hh;
00202 headline.GetPixelSize(out hw, out hh);
00203 double height = hh + 10 + 10 + 10;
00204
00205
00206 double pageHeight = args.Context.Height - 20;
00207 int pageCount = 1;
00208 foreach(ShoppingListItemAdapter item in this.shoppingListStore){
00209 var h = item.AdjustWidth(qWidth, dWidth);
00210 if(h + height > pageHeight){
00211 pageCount++;
00212 height = h;
00213 }else
00214 height += h;
00215 }
00216
00217 (o as PrintOperation).NPages = pageCount;
00218 args.RetVal = true;
00219 };
00220
00221 IEnumerator rows = null;
00222
00223 p.DrawPage += delegate(object o, DrawPageArgs args)
00224 {
00225
00226 Cairo.Context context = args.Context.CairoContext;
00227
00228 context.SetSourceRGB(0 ,0 ,0);
00229
00230
00231 context.LineCap = Cairo.LineCap.Round;
00232 context.LineWidth = 2;
00233
00234 context.MoveTo(10, 10);
00235 Cairo.PointD pos = context.CurrentPoint;
00236
00237 if(rows == null){
00238
00239 context.LineTo(args.Context.Width - 10, 10);
00240 context.Stroke();
00241 context.MoveTo(10, 20);
00242
00243
00244 int width, height;
00245 headline.GetPixelSize(out width, out height);
00246
00247
00248 Pango.CairoHelper.ShowLayout(context, headline);
00249
00250
00251 context.RelMoveTo(0, height + 10);
00252 pos = context.CurrentPoint;
00253 context.RelLineTo(args.Context.Width - 20, 0);
00254 context.Stroke();
00255 context.MoveTo(pos);
00256 context.RelMoveTo(0, 10);
00257 pos = context.CurrentPoint;
00258
00259
00260 rows = this.shoppingListStore.GetEnumerator();
00261 if(!rows.MoveNext())
00262 return;
00263 }
00264
00265
00266 double tableY = pos.Y;
00267
00268 do{
00269 ShoppingListItemAdapter row = (ShoppingListItemAdapter)rows.Current;
00270 if(row.NextPage(args.Context.Width - pos.X, args.Context.Height - pos.Y - 10))
00271 break;
00272 pos.Y += row.Render(context, pos, qWidth);
00273 }while(rows.MoveNext());
00274
00275
00276 context.LineWidth = 1;
00277 context.SetDash(new double[]{5, 5}, 0);
00278 context.MoveTo(10 + qWidth + 5, tableY);
00279 context.LineTo(10 + qWidth + 5, pos.Y + 5);
00280 context.Stroke();
00281 };
00282 p.Run(PrintOperationAction.PrintDialog, this.owner.Window);
00283 p.Dispose();
00284 }
00285
00291 protected virtual void OnBtnCookbookClicked(object sender, System.EventArgs e)
00292 {
00293 this.owner.PushActivity("Cookbook");
00294 }
00295
00301 protected virtual void OnBtnDeleteClicked(object sender, System.EventArgs e)
00302 {
00303 ShoppingListItemAdapter selectedNode = (ShoppingListItemAdapter)this.shoppingListViewer.NodeSelection.SelectedNode;
00304 if (selectedNode != null)
00305 this.shoppingListStore.RemoveNode(selectedNode);
00306 this.shoppingList.RemoveIngredient(selectedNode.Item.Ingredient);
00307 }
00308
00309 private void SetDeleteButtonState()
00310 {
00311 if (this.shoppingListViewer.NodeSelection.SelectedNode != null)
00312 this.btnDelete.Sensitive = true;
00313 else
00314 this.btnDelete.Sensitive = false;
00315 }
00316
00317 protected virtual void OnShoppingListViewerCursorChanged(object sender, System.EventArgs e)
00318 {
00319 SetDeleteButtonState();
00320 }
00321
00331 protected virtual void OnShoppingListViewerRowActivated (object o, Gtk.RowActivatedArgs args)
00332 {
00333 var shoppingItem = (ShoppingListItemAdapter)this.shoppingListViewer.NodeSelection.SelectedNode;
00334 IngredientSelector selector = new IngredientSelector(shoppingItem.Item.Ingredient);
00335 if(selector.Run() == (int)ResponseType.Ok){
00336 if(!shoppingList.ContainsIngredient(selector.SelectedIngredient)) {
00337 shoppingItem.Item.Ingredient = selector.SelectedIngredient;
00338 shoppingList.Save();
00339 LoadShoppingListData();
00340 } else {
00341 ShowIngredientAlreadyAddedMessage();
00342 }
00343 }
00344 selector.Destroy();
00345 }
00346
00347 private void ShowIngredientAlreadyAddedMessage(){
00348 MessageDialog diag =
00349 new MessageDialog(this.owner.Window,
00350 DialogFlags.Modal,
00351 MessageType.Info,
00352 ButtonsType.Ok,
00353 @"The selected ingredient is already in your shopping list.
00354 Please update the quantity if you wish to add more.");
00355 if(diag.Run() == (int)ResponseType.Ok){}
00356 diag.Destroy();
00357 }
00358
00359 }
00360 }