]> err.no Git - scalable-opengroupware.org/commitdiff
added some TB icons, added alternative viewer
authorhelge <helge@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Tue, 5 Oct 2004 12:22:31 +0000 (12:22 +0000)
committerhelge <helge@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Tue, 5 Oct 2004 12:22:31 +0000 (12:22 +0000)
git-svn-id: http://svn.opengroupware.org/SOGo/trunk@356 d1b88da0-ebda-0310-925b-ed51d893ca5b

15 files changed:
SOGo/UI/Mailer/ChangeLog
SOGo/UI/Mailer/GNUmakefile
SOGo/UI/Mailer/Images/message-mail-read.png [new file with mode: 0755]
SOGo/UI/Mailer/Images/message-mail.png [new file with mode: 0755]
SOGo/UI/Mailer/README
SOGo/UI/Mailer/UIxMailPartAlternativeViewer.m [new file with mode: 0644]
SOGo/UI/Mailer/UIxMailPartAlternativeViewer.wox [new file with mode: 0644]
SOGo/UI/Mailer/UIxMailPartMixedViewer.m
SOGo/UI/Mailer/UIxMailPartViewer.h
SOGo/UI/Mailer/UIxMailPartViewer.m
SOGo/UI/Mailer/UIxMailRenderingContext.h
SOGo/UI/Mailer/UIxMailRenderingContext.m
SOGo/UI/Mailer/Version
SOGo/UI/Mailer/mailer.css
SOGo/UI/Mailer/product.plist

index c7f2f4a39e35005913be0dc089e4f6f23b272e37..7d4259c335b472c667d273c594ff44ba852ead06 100644 (file)
@@ -1,3 +1,14 @@
+2004-10-05  Helge Hess  <helge.hess@opengroupware.org>
+
+       * v0.9.18
+       
+       * UIxMailPartViewer.m: added support methods for caches, added -sleep
+         method
+       
+       * added multipart/alternative viewer
+       
+       * added Thunderbird message read/unread icons
+
 2004-10-04  Helge Hess  <helge.hess@opengroupware.org>
 
        * fixed fetching of mails with only text content (v0.9.17)
index 9a09fea5071cd952d3a5bc7fedd7e5d4633673f9..aacadd4e0c8d7a0e5b3e136815e6ed915116046e 100644 (file)
@@ -26,10 +26,11 @@ MailerUI_OBJC_FILES += \
        UIxMailView.m           \
        UIxMailEditor.m         \
        \
-       UIxMailPartViewer.m     \
-       UIxMailPartTextViewer.m \
-       UIxMailPartImageViewer.m\
-       UIxMailPartMixedViewer.m
+       UIxMailPartViewer.m             \
+       UIxMailPartTextViewer.m         \
+       UIxMailPartImageViewer.m        \
+       UIxMailPartMixedViewer.m        \
+       UIxMailPartAlternativeViewer.m  \
 
 MailerUI_RESOURCE_FILES += \
        Version                 \
@@ -48,6 +49,7 @@ MailerUI_RESOURCE_FILES += \
        UIxMailPartTextViewer.wox       \
        UIxMailPartMixedViewer.wox      \
        UIxMailPartImageViewer.wox      \
+       UIxMailPartAlternativeViewer.wox\
 
 MailerUI_RESOURCE_FILES += \
        uix.css                 \
@@ -59,6 +61,7 @@ MailerUI_RESOURCE_FILES += \
        Images/tbtv_*.gif       \
        Images/icon_*.gif       \
        Images/tbtb_*.png       \
+       Images/message-mail*.png\
        Images/lori_32x32.png   \
 
 MailerUI_LOCALIZED_RESOURCE_FILES += \
diff --git a/SOGo/UI/Mailer/Images/message-mail-read.png b/SOGo/UI/Mailer/Images/message-mail-read.png
new file mode 100755 (executable)
index 0000000..17d5784
Binary files /dev/null and b/SOGo/UI/Mailer/Images/message-mail-read.png differ
diff --git a/SOGo/UI/Mailer/Images/message-mail.png b/SOGo/UI/Mailer/Images/message-mail.png
new file mode 100755 (executable)
index 0000000..c58e099
Binary files /dev/null and b/SOGo/UI/Mailer/Images/message-mail.png differ
index fe93331626ff6295ba79e198d97caaec6fe8514a..9cbcaeb178f547308ba93d80de2efae78bd1b718 100644 (file)
@@ -22,6 +22,16 @@ UIxMailView.wox
 Notes
 =====
 
+- we might want to bind the content viewers as SOPE methods to the mail class?
+  eg "viewTextPlain"
+  - this would not return a WOComponent, but a SoPageInvocation
+  - caching might be more difficult 
+    - some 'reuse component' support in SoPageInvocation for stateless
+      components?
+      - watch nested calls
+  - for this we would need to add support for embedded calling of SOPE methods
+    <var:component method="viewTextPlain" /> ?
+
 Bodystructures
 ==============
 
diff --git a/SOGo/UI/Mailer/UIxMailPartAlternativeViewer.m b/SOGo/UI/Mailer/UIxMailPartAlternativeViewer.m
new file mode 100644 (file)
index 0000000..95f5345
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+  Copyright (C) 2004 SKYRIX Software AG
+
+  This file is part of OpenGroupware.org.
+
+  OGo is free software; you can redistribute it and/or modify it under
+  the terms of the GNU Lesser General Public License as published by the
+  Free Software Foundation; either version 2, or (at your option) any
+  later version.
+
+  OGo is distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with OGo; see the file COPYING.  If not, write to the
+  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+  02111-1307, USA.
+*/
+
+#include "UIxMailPartViewer.h"
+
+/*
+  UIxMailPartAlternativeViewer
+  
+  Display multipart/alternative parts. Most common application is for messages
+  which contain text/html and text/plain, but it is also used in other
+  contexts, eg in OGo appointment mails.
+  
+  TODO: We might want to give the user the possibility to access all parts
+        of the alternative set.
+*/
+
+@interface UIxMailPartAlternativeViewer : UIxMailPartViewer
+{
+  id           childInfo;
+  unsigned int childIndex;
+}
+
+@end
+
+#include "UIxMailRenderingContext.h"
+#include "WOContext+UIxMailer.h"
+#include "common.h"
+
+@implementation UIxMailPartAlternativeViewer
+
+- (void)dealloc {
+  [self->childInfo release];
+  [super dealloc];
+}
+
+/* caches */
+
+- (void)resetBodyInfoCaches {
+  [self->childInfo release]; self->childInfo = nil;
+  self->childIndex = 0;
+  [super resetBodyInfoCaches];
+}
+
+/* part selection */
+
+- (NSArray *)childPartTypes {
+  NSMutableArray *types;
+  unsigned i, count;
+  NSArray  *childParts;
+
+  childParts = [[self bodyInfo] valueForKey:@"parts"];
+  count      = [childParts count];
+  types      = [NSMutableArray arrayWithCapacity:count];
+  
+  for (i = 0; i < count; i++) {
+    NSString *mt, *st;
+
+    mt = [[[childParts objectAtIndex:i] valueForKey:@"type"] lowercaseString];
+    st = [[[childParts objectAtIndex:i] valueForKey:@"subtype"]
+                      lowercaseString];
+    mt = [[mt stringByAppendingString:@"/"] stringByAppendingString:st];
+    [types addObject:mt ? mt : (id)[NSNull null]];
+  }
+  return types;
+}
+
+- (int)selectPartIndexFromTypes:(NSArray *)_types {
+  /* returns the index of the selected part or NSNotFound */
+  unsigned i, count;
+
+  if ((count = [_types count]) == 0)
+    return NSNotFound;
+  
+  /* we always choose text/plain if available */
+  if ((i = [_types indexOfObject:@"text/plain"]) != NSNotFound)
+    return i;
+  
+  /* then we scan for other text types and choose the first one found */
+  for (i = 0; i < count; i++) {
+    if ([(NSString *)[_types objectAtIndex:i] hasPrefix:@"text/"])
+      return i;
+  }
+  
+  /* as a fallback, we select the first available part */
+  return 0;
+}
+
+- (void)selectChildInfo {
+  unsigned idx;
+  
+  [self->childInfo release]; self->childInfo = nil;
+  self->childIndex = 0;
+  
+  idx = [self selectPartIndexFromTypes:[self childPartTypes]];
+  if (idx == NSNotFound) {
+    [self logWithFormat:@"ERROR: could not select a part of types: %@",
+           [self childPartTypes]];
+    return;
+  }
+  
+  self->childIndex = idx + 1;
+  self->childInfo  = 
+    [[[[self bodyInfo] valueForKey:@"parts"] objectAtIndex:idx] retain];
+}
+
+/* accessors */
+
+- (id)childInfo {
+  if (self->childInfo == nil)
+    [self selectChildInfo];
+  
+  return self->childInfo;
+}
+
+- (unsigned int)childIndex {
+  if (self->childIndex == 0)
+    [self selectChildInfo];
+  
+  return self->childIndex - 1;
+}
+
+- (NSString *)childPartName {
+  unsigned char buf[8];
+  sprintf(buf, "%d", [self childIndex] + 1);
+  return [NSString stringWithCString:buf];
+}
+
+- (id)childPartPath {
+  NSArray *pp;
+
+  pp = [self partPath];
+  return [pp count] > 0
+    ? [pp arrayByAddingObject:[self childPartName]]
+    : [NSArray arrayWithObject:[self childPartName]];
+}
+
+/* nested viewers */
+
+- (id)contentViewerComponent {
+  id info;
+  
+  info = [self childInfo];
+  return [[[self context] mailRenderingContext] viewerForBodyInfo:info];
+}
+
+@end /* UIxMailPartAlternativeViewer */
diff --git a/SOGo/UI/Mailer/UIxMailPartAlternativeViewer.wox b/SOGo/UI/Mailer/UIxMailPartAlternativeViewer.wox
new file mode 100644 (file)
index 0000000..8573896
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" standalone="yes"?>
+<div xmlns="http://www.w3.org/1999/xhtml"
+     xmlns:var="http://www.skyrix.com/od/binding"
+     xmlns:const="http://www.skyrix.com/od/constant"
+     xmlns:rsrc="OGo:url"
+     xmlns:label="OGo:label"
+>
+  <div>
+    <var:component value="contentViewerComponent" 
+                   bodyInfo="childInfo"
+                  partPath="childPartPath" />
+  </div>
+</div>
index 4a7b9d36c87c133a9527f5ce8c9758f74b9355ad..099fbf00ddca5940367dcde44a2065a781f7b7a8 100644 (file)
   [super dealloc];
 }
 
-/* notifications */
+/* caches */
 
-- (void)sleep {
+- (void)resetBodyInfoCaches {
   [self->childInfo release]; self->childInfo = nil;
-  [super sleep];
+  [super resetBodyInfoCaches];
 }
 
 /* accessors */
index 9e1f6f554e7a185318192cb261a25e8109d53070..a5551f08c0e35f155f10e1ce34fdad4edbf44860 100644 (file)
 
 - (NSData *)flatContent;
 
+/* caches */
+
+- (void)resetPathCaches;
+- (void)resetBodyInfoCaches;
+
 @end
 
 #endif /* __Mailer_UIxMailPartViewer_H__ */
index a043481c8677ffe4ba3078b9378b81bb468a5e6a..e172aac42062d4062ee8ad0f5dc0c8d2c1ef08a0 100644 (file)
   [super dealloc];
 }
 
+/* caches */
+
+- (void)resetPathCaches {
+  [self->flatContent release]; self->flatContent = nil;
+}
+- (void)resetBodyInfoCaches {
+}
+
+/* notifications */
+
+- (void)sleep {
+  [self resetPathCaches];
+  [self resetBodyInfoCaches];
+  [self->partPath release]; self->partPath = nil;
+  [self->bodyInfo release]; self->bodyInfo = nil;
+  [super sleep];
+}
+
 /* accessors */
 
 - (void)setPartPath:(NSArray *)_path {
+  if ([_path isEqual:self->partPath])
+    return;
+  
   ASSIGN(self->partPath, _path);
+  [self resetPathCaches];
 }
 - (NSArray *)partPath {
   return self->partPath;
index 4f47116167f270277951633f1eea8766a3a0f9fd..672a5eb0718c48c7c8f4ebc9a13a6eb2545fd987 100644 (file)
@@ -38,7 +38,8 @@
   WOComponent  *viewer;       /* non-retained! */
   WOContext    *context;      /* non-retained! */
   NSDictionary *flatContents; /* IMAP4 name to NSData */
-  
+
+  WOComponent *alternativeViewer;
   WOComponent *mixedViewer;
   WOComponent *textViewer;
   WOComponent *imageViewer;
index f30f224069c891f90b3ba04ef848ba3dfb57cd03..b7aac88a52bf5579049ff214690525a7162c3eb5 100644 (file)
@@ -40,6 +40,7 @@
 }
 
 - (void)dealloc {
+  [self->alternativeViewer release];
   [self->mixedViewer release];
   [self->textViewer  release];
   [self->imageViewer release];
 /* resetting state */
 
 - (void)reset {
-  [self->flatContents release]; self->flatContents = nil;
-  [self->mixedViewer  release]; self->mixedViewer  = nil;
-  [self->textViewer   release]; self->textViewer   = nil;
-  [self->imageViewer  release]; self->imageViewer  = nil;
+  [self->flatContents      release]; self->flatContents      = nil;
+  [self->alternativeViewer release]; self->alternativeViewer = nil;
+  [self->mixedViewer       release]; self->mixedViewer       = nil;
+  [self->textViewer        release]; self->textViewer        = nil;
+  [self->imageViewer       release]; self->imageViewer       = nil;
 }
 
 /* fetching */
   return self->mixedViewer;
 }
 
+- (WOComponent *)alternativeViewer {
+  if (self->alternativeViewer == nil) {
+    self->alternativeViewer =
+      [[self->viewer pageWithName:@"UIxMailPartAlternativeViewer"] retain];
+  }
+  return self->alternativeViewer;
+}
+
 - (WOComponent *)textViewer {
   if (self->textViewer == nil) {
     self->textViewer = 
       return [self mixedViewer];
     if ([st isEqualToString:@"signed"]) // TODO: temporary workaround
       return [self mixedViewer];
+    if ([st isEqualToString:@"alternative"])
+      return [self alternativeViewer];
   }
   else if ([mt isEqualToString:@"text"]) {
     if ([st isEqualToString:@"plain"])
       return [self textViewer];
+    if ([st isEqualToString:@"html"])
+      return [self textViewer]; // TODO: temporary workaround
   }
   else if ([mt isEqualToString:@"image"])
     return [self imageViewer];
       pgp-viewer
     */
   }
-  
+
+  // TODO: always fallback to octet viewer?!
   [self logWithFormat:@"ERROR: found no viewer for MIME type: %@/%@", mt, st];
   return nil;
 }
index 33dfbe1b04726220aa5142e7e070a02c182f5657..cd35ad0fc7134df7fcc93aab18344f258f338c2b 100644 (file)
@@ -1,3 +1,3 @@
 # $Id$
 
-SUBMINOR_VERSION:=17
+SUBMINOR_VERSION:=18
index 8a8186c3d8c589141b6dc8be561ceb2c6ded76cc..1c95da26d0d71419e3139eeb1f68f3441e734d25 100644 (file)
@@ -197,7 +197,8 @@ span.mailer_datefield {
 
 div.mailer_readmailsubject { 
   /* TODO: use proper read icon */
-  background-image:    url(tbtv_leaf_corner_17x17.gif);
+  /* background-image:    url(tbtv_leaf_corner_17x17.gif); */
+  background-image:    url(message-mail-read.png);
   background-repeat:   no-repeat;
   background-position: 0px 0px;
   padding-top:         1px;
@@ -205,7 +206,8 @@ div.mailer_readmailsubject {
 }
 div.mailer_unreadmailsubject { 
   /* TODO: use proper unread icon */
-  background-image:    url(tbtv_leaf_corner_17x17.gif);
+  /* background-image:    url(tbtv_leaf_corner_17x17.gif); */
+  background-image:    url(message-mail.png);
   background-repeat:   no-repeat;
   background-position: 0px 0px;
   padding-left:        20px;
index 01e2f9a5447c538557da8a668b111e2e82b9a5c1..f272c668f0dbb915fd5572dbb7016f5f43f9ec1d 100644 (file)
@@ -38,6 +38,9 @@
     "tbtb_search.png",
     "tbtb_trash.png",
 
+    "message-mail.png",
+    "message-mail-read.png",
+
     "icon_mark_flagged.gif",
     "icon_mark_read.gif",
     "icon_mark_unflagged.gif",